《计算机程序构造与解释》读书笔记(3)

news2025/2/2 13:04:09

1. 写在最前面

越是浮躁的时候,越是需要想办法让自己从这种心境中脱离。

2. 设计的取舍

有效的程序需要一些组织原则,以指导系统化地完成整体设计。比如,使系统能够「自然地」划分为一些具有内聚力的部分,使其可以分别进行开发和维护。

  • 一种策略将注意力集中在对象上,将一个大型系统看成一大批对象,它们的行为可能随着时间的进展而不断变化
  • 一种组织策略将注意力集中在流过系统的信息流上,非常像电子工程师观察一个信号处理系统

注: 一种非常强有力的设计策略,基于被模拟系统的结构去设计程序结构。有关的物理系统里的每个对象,构造一个与之对应的计算对象;该系统里的每种活动,定义一种符号操作。

3. 赋值和局部状态

关于世界的常规观点之一,就是将它看做聚集在一起的许多独立对象,每个对象都有自己随着时间变化的状态。所谓一个对象「有状态」,也就是说它的行为受到它的历史影响。

注:例如一个银行账户就具有状态,对问题「我能取出 100 元钱吗?」的回答依赖于它的存入和支取的交易历史。

在一个由许多对象组成的系统里,其中的这些对象极少会是完全独立的。每个对象都可能通过交互作用,影响其他对象的状态,所谓交互就是建立起一个对象的状态变量与其他对象的状态变量之间的联系。

注: 要使模型成为模块化的,就要求它能分解为一批计算对象,使它们能够模拟系统里的实际对象。每一个计算对象必须有它自己的一些「局部状态变量」,用于描述实际对象的状态

通过程序设计语言里常规的符号名称去模拟状态变量,那么语言里就必须提供一个赋值运算符,使能用它去改变一个名字相关联的值。

3.1 局部状态变量

将 「set !」与局部变量相结合,形成了一种具有一般性的程序设计技术,将使用这种技术去构造带有局部状态的计算对象。

一旦在语言里引用了赋值,代换就不再适合作为过程应用的模型了。

注:代换模型,将过程的形式参数用对应的值取代之后求值这一过程的体。

3.2 引进赋值带来的利益

将系统看作是带有局部状态的对象,也是一种维护模块化设计的强有力技术。

与所有状态都必须显式地操作和传递额外参数的方式相比,通过引入赋值和将状态隐藏在局部变量中的技术,我们能以一种更模块化的方式构造系统。

3.3 引进赋值的代价

一旦引进了「set !」和变量的值可以变化的想法,一个变量就不在是一个简单的名字了。现在的一个变量索引着一个可以保存值的位置,而存储在那里的值也是可以改变的。

注:只要不使用赋值,以同样参数对同一过程的两次求值一定产生出同样的结果。不使用任何赋值的程序设计称为函数式程序设计

3.3.1 同一和变化

引入赋值的代价,远远不是简单地打破一个特定计算模型那么简单。一旦将变化引进到计算模型,许多非常简单明了的概念现在都变得有问题了。

如果一个语言支持在表达式里「同一个东西可以相互替换」的观念,这样替换不会改变有关表达式的值,这个语言就称为是具有引用透明性。在计算机语言里包含了「set !」之后,也就打破了引用透明性,就使确定能够通过等价的表达式去简化表达式变成了一个异常错综复杂的问题。

注:一般而言,只能用如下方式确定两个看起来同一的事物是否确实是「同一个东西」:改变其中的一个对象,去看另一个对象是否也同样的改变了。

​ 但是,如果不通过观察「同一个」对象两次,看看一次观察中看到的某些对象性质与另一次不同,又怎么能说清楚一个对象是否「变化」了呢?

3.3.2 命令式程序设计的缺陷

与函数式程序设计相对应的,广泛采用赋值的程序设计被称为命令式程序设计。除了会导致计算模型的复杂性之外,以命令式风格写出的程序还容易出现一些不会在函数式程序中出现的错误。

注:带有赋值的程序将强迫人们去考虑赋值的相对顺序,以保证每个语句所用的是被修改变量的正确版本。

4. 求值的环境模型

一个环境就是框架的一个序列,每个框架里包含着一些约束的一个表格,这些约束将一些变量名字关联于对应的值。每个框架还包含着一个指针,指向这一框架的外围环境。

一个变量相对于某个特定环境的值,也就是在这一环境中,包含着该变量的第一个框架里这个变量的约束值。如果在序列中并不存在这一变量的约束,就说这个变量在该特定环境中是无约束的。

注:环境对于求值过程是至关重要的,因为它确定了表达式求值的上下文。在一个程序语言里的一个表达式本身根本没有任何意义。即使像(+ 1 1)这样极其简单的表达式,其解释也要依赖于有关的操作是在某个上下文里进行的,在那里 + 是表示加法的符号。

4.1 求值规则

如果要对一个组合表达式求值

  • 求值这一组合式里的各个子表达式
  • 将运算符子表达式的值应用于运算对象

环境模型说明:在将一个过程应用于一组实际参数时,将会建立起一个新环境,其中包含了将所有形式参数约束于对应的实际参数的框架,该框架的外围环境就是所用的那个过程的环境。

注:虽然这一求值模型比较抽象,但它却为解释器对于表达式求值的过程提供了一个正确的描述。

4.2 简单过程的应用

思考组合式 (f 5) 怎么求值得到 136:

(define (square x)
   (* x x))
(define (sum-of-squares x y)
   (+ (square x)(square y)))
(define (f a)
   (sum-of-squares (+ a 1)(* a 2)))

求值过程如下图:

在这里插入图片描述

注:此处关系的是环境结构,因此不详细考察这些返回值如何在调用之间传递的问题

4.3 将框架看做局部状态的展台

从环境模型出发,用过程和赋值表示带有局部状态的对象,以下面的创建「提款处理器」为例:

(define (make-withdraw balance)
   (lambda (amount)
      (if (>= balance amount)
          (begin (set! balance (- balance amount))
                  balance)
           "Insufficient funds")))

构造如下两个实例:

  • (define W1 (make-withdraw 50))
  • (define W2 (make-withdraw 100))

W1 和 W2 是两个不同的过程对象,W1 和 W2 具有相同的代码,即在 make-withdraw 内的 lambda 表达式所确定的代码,但是却具有者不同的对 balance 的局部约束。

在这里插入图片描述

4.4 内部定义

环境模型已经解释清楚了以局部过程定义作为程序模块化的有用技术中的两个关键性质:

  • 局部过程的名字不会与包容它们的过程之外的名字互相干扰,这是因为这些局部过程名都是在该过程运行时创建的框架里面的约束的,而不是在全局环境里约束的。
  • 局部过程只需将包含着它们的过程的形参作为自由变量,就可以访问该过程的实际参数。这是因为对于局部过程体的求值所在的环境是外围过程求值所在的环境的下属。

5. 用变动数据做模拟

为了模拟具有不断变化的状态的复合对象,需要设计出阈值对应的数据抽象,使其不但包含选择函数和构造函数,还包含一些称为「改变函数」的操作,这种操作能修改有关的数据对象。

注:改变函数能够极大地提升序对的表达能力,使其能构造出序列和树之外的其他数据结构。

5.1 变动的表结构

针对序对的基本操作— cons、car 和 cdr — 能用于构造表结构,或者选出表结构中的各个部分,但它们不能修改表结构。

注:至今用过的其他表结构,比如 append 和 list 也都是如此,它们都可以基于 cons 、car 和 cdr 定义出来。

要修改表结构就需要新的操作,针对序对的基本改变函数是 set-car! 和 set-cdr!。cons 通过创建新的序对的方式构造新的表,而 set-car! 和 set-cdr! 则是需改现存的序对。

5.1.1 共享和相等

由于引入赋值而产生的「同一」和「变化」的理论问题,当不同的数据对象共享某些序对是,这些问题就表现到现实中来了。

注:如果只用 cons、car 和 cdr 对各种表进行操作,其中的共享完全不会被察觉。然而,如果允许改变表结构的话,共享的情况就会显现出来。

检查表结构是否共享的一种方式是使用谓词 eq?,比如(eq? x y)检查 x 和 y 是否为同一个对象,即 x 和 y 作为指针是否相等。

利用共享结构可以极大的扩展能够用序对表示的数据结构范围。在另一方面,共享也可能带来危险,因为对这种结构的修改将会影响那些恰好共享这被修改了的序对的结构。

5.1.2 改变也就是赋值

从理论上说,为了表现变动数据的行为,所需要的全部东西也就是赋值。只要将赋值纳入这一语言,就引出了所有的问题,不仅是赋值,而且也包括一般性的变动对象。

5.2 队列的表示

利用改变函数 set-car! 和 set-cdr!,可以用序对构造出一些单靠 cons、car 和 cdr 无法构造的数据结构。本节将展示用序对表示一种称为序对的数据结构。

一个队列是一个序对,数据项只能从一端插入(队尾)只能从另一端删除(队头),按照数据抽象的说法,队列可以看作是由下面一组操作定义的数据结构:

  • 一个构造函数 (make-queue),它返回一个空队列,不包含数据项的队列
  • 两个选择函数:
    • (empty-queue? <queue>)检查队列是否为空
    • (front-queue <queue>)返回队列前端的对象,如果队列为空就报告一个错误,它不修改队列。
  • 两个改变函数
    • (insert-queue! <queue><item>)将数据项插入队列末端,返回修改过的队列作为值
    • (delete-queue! <queue>)删除队列前端的数据项,并返回修改后的队列作为值,如果删除之前队列为空就报告错误。

队列引入了一个问题是为找到表尾需要扫描整个表。如果要避免这一缺陷,那就需要修改表示方式,将队列表示一个表,并带有一个指向表的最后序对的指针。

5.3 表格的表示

5.3.1 一维表格

每个值保存在一个关键码之下,将这种表格实现为一个记录的表,其中的每个记录将实现一个关键码和一个关联值组成的序对。将这种记录连接起来构成一个序对的表,这些作为连接结构的序对就成为这一表格的骨架。

一维表格的示例图如下:

在这里插入图片描述

5.3.2 二维表格

两维表格里的每个值由两个关键码索引。将这种表格构造为一个一维表格,其中的每个关键码又标识了一个子表格。

在这里插入图片描述

注:在需要查找一个数据项时,先用第一个关键码确定对应的子表格,然后第二个关键码在这个子表格里确定记录。

5.3.3 创建局部表格

上面定义的 lookup 和 insert! 操作都以表格作为一个参数,这可以将它们用到包含多个表格的程序里。处理多个表格的另一种方式是为每个表格提供一对独立的 lookup 和 insert! 过程。

5.4 数字电路的模拟器

设计复杂的数字系统,例如计算机,是一种非常重要的工程活动。数字系统都是通过连接一些简单元件构造起来的。虽然这些元件单独看起来功能都很简单,它们连接起来形成的网络就可能产生非常复杂的行为。

注:本节将设计一个执行数字逻辑模拟的系统,这一系统是通常被称为事件驱动的模拟程序的一个典型代表。

可以将一些基本功能部件连接起来,构造出更复杂的功能。比如下图的半加器电路,其中包括一个或门、两个与门和一个反门。

在这里插入图片描述

注:做出这种稍复杂组件的好处是,可以基于其作为基本构建,去创建更复杂的电路,比如基于半加器去构造全加器

从本质上看,模拟器提供了一种工具,作为构造电路的一种语言。各种基本功能块形成了这个语言的基本元素,将功能块连接起来就是这里的组合方法,而将特定的连接模式定义为过程就是这里的抽象方法。

5.4.1 基本功能块

基本功能块实现一种「效能」,使得在一根连线上的信号变化能够影响其他连线上的信号。为了构造出这些功能块,需要连线上的如下操作:

  • (get-signal <wire>)返回连线上信号的当前值
  • (set-signal! <wire> <new value>)将连线上的信号修改为新的值
  • (add-action! <wire> <procedure of no arguments>)只要在连线上的信号值改变,这里所指定过程就需要运行。这种过程是一些媒介,它们能够将相应连线上的值变化传递到其他的连线。

利用这些过程,就可以定义基本的数字逻辑功能。

5.4.2 线路的表示

在这种模拟中,一条线路也就是一个具有两个局部状态变量的计算对象:其中一个是信号值 signal-value(其初始值取 0),另一个是一组过程 action-procedures,在信号改变时,这些过程都需要运行。

注:一条线路被所有连接在该线路上的各种设备所共享。这样,由一个设备交互所造成的变化就会影响到连接在这条线路上的其他设备。

5.4.3 待处理表

为完成这一模拟器,剩下的就是 after-delay。这里的想法是维护一个称为待处理表的数据结构,其中包含着一个需要完成的事项清单。对于这个待处理表,定义如下操作:

  • (make-agenda)返回一个新的空的待处理表
  • (empty-agenda? <agenda>)在所给待处理表空时为真
  • (first-agenda-item <agenda>)返回待处理表里的第一个项目
  • (remove-first-agenda-item! <agenda>)修改待处理表,删除其中的第一个项目
  • (add-to-agenda! <time> <action> <agenda>)修改待处理表,加入一项,要求在特定时间允许给定的动作过程
  • (current-time <agenda>)返回当前的模拟时间

5.4.4 一个简单的实例模拟

下面过程中将一个「监视器」放在一个线路上,用于显示模拟器的活动。这一过程告诉相应的线路,只要它的值改变了,就应该打印出新的值,同时打印当前的时间和线路名字:

(define (probe name wire)
   (add-action! wire
                 (lambda()
                    (newline)
                    (display name)
                    (display " ")
                    (display (current-time the-agenda))
                    (display " New-value = ")
                    (display (get-signal wire)))))

5.4.5 待处理表的实现

介绍待处理表数据结构的细节,这一数据结构里面保存着已经安排好,将在未来时刻运行的那些过程。这种待处理表由一些时间段组成,每个时间段是由一个数值(表示时间)和一个队列组成的序对,在这个队列里,保持着那些已经安排好的,应该在这一段时间运行的过程。

5.5 约束的传播

在传统上,计算机程序总被组织成一种单向的计算,它们对一些事先给定的参数执行某些操作,产生所需要的输出。但在另一方面,也经常需要模拟一些由各种量之间的关系描述符系统。

比如某个机械结构的数学模型里可能包含着这样的一些信息:在一个金属杆的偏转量 d 与作用于这个杆的力 F、杆的长度 L、截面面积 A 和弹性模数之间的关系可以由下面的方程描述: dAE = FL

注:这种关系并不是单向的,给定其中的任意的 4 个量,就可以利用它计算第 5 个量。

本节要描绘一种语言的设计,这种语言可以基于各种关系进行工作。这一语言里的基本元素就是「基本约束」,它们描述了不同量之间的某种特定关系。通过组合各种基本约束,以便于去描述更复杂的关系。

注:例如 (adder a b c)描述的是量 a、b 和 c 之间必须有关系 a + b = c

5.5.1 约束系统的使用

例子,在华氏温度和摄氏温度之间的关系是:9C = 5(F - 32),为了使用约束的系统模型去执行温度计算,需要首先调用构造函数 make-connector,创建起两个连接器 C 和 F,然后将它们连接到一个适当的网络里:

(defile C (make-connector))
(defile F (make-connector))
(celsius-fahrenheit-converter C F)
OK 

创建上述网络的过程定义如下:

(define (celsius-fahrenheit-converter C F)
   (let ((u (make-connector))
         (v (make-connector))
         (w (make-connector))
         (x (make-connector))
         (y (make-connector))
      (multiplier c w u)
      (multiplier v x u)
      (adder v y f)
      (constant 9 w)
      (constant 5 x)
      (constant 32 y)
      'ok))

这一过程建立起内部连接器 u、v、w、x 和 y,调用基本约束的构造函数 adder、multiplier 和 constant ,并按照定义将它们连接起来。

5.5.2 约束系统的实现

约束系统用具有内部状态的过程对象实现。

注:虽然约束系统里的基本对象在某些方面更复杂一些,但整个系统却更为简单,因为这里完全不需要关心待处理表和时间延迟等等问题。

连接器的基本操作包括:

  • (has-value? <connector>)报告说这一连接器是否有值
  • (get-vlaue <connector>)返回连接器当前的值
  • (set-value ! <connector><new-value><informant>)通知说,信息源(informant)要求连接器将其值设置为一个新值
  • (forget-value! <connector><retractor>)通知说,撤销源(retractor)要求连接器忘记其值。
  • (connect <connector><new-constraint>)通知连接器参与一个新约束

5.5.3 连接器的表示

连接器用带有局部状态变量 value、informant 和 constraints 的过程对象表示,value 中保持这个连接器的当前值,informant 是设置连接器值的对象,constraints 是这一连接器所涉及的所有约束的表。

6. 碎碎念

断断续续的看了一周也只记录完成一周的 3/5 ,我只能说经典的书籍被称之为经典不是木有原因的。希望在年前能把第三章全部看完吧(ps: 发现最近接触过的人确诊阳性的越来越多了,这大概是我离确诊新冠最近的一次

  • 你要记得那些黑暗中默默抱紧你的人、逗你笑的人、陪你聊天的人、坐车来看望你的人、带你四处游荡的人、说想念你的人。是这些人组成你生命中一点一滴的温暖,是这些温暖使你远离阴霾,是这些温暖使你成为善良的人。
  • 我始终相信,我读过的所有书都不会白读,它总会在未来日子的某一场合,帮助我表现得更加出色。
  • 还是要保持因生活细碎而快乐的能力,比如品尝久违的美食,重温熟悉的街角,买到中意的裙子,这些看似零碎的生活碎片却是通往快乐星球的秘密通道。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/104059.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Mycat(13):全局表和普通表的配置和测试

1 全局表概述 一个真实的业务系统中&#xff0c;往往存在大量的类似字典表的表格&#xff0c;它们与业务表之间可能有关系&#xff0c;这种关系&#xff0c;可以理解为“标签”&#xff0c;而不应理解为通常的“主从关系”&#xff0c;这些表基本上很少变动&#xff0c;可以根…

Spring Security认证和授权

Spring Security认证和授权 一、Spring Security的认识 Spring Security是Spring家族中的一个安全管理框架。相比与另外一个安全框架Shiro&#xff0c;它提供了更丰富的功能&#xff0c;社区资源也比Shiro丰富。 一般来说中大型的项目都是使用SpringSecurity来做安全框架。小…

Windows C语言 UDP通信demo

目录编译环境快速入门编译指令服务端code客户端code参考文章以及遇到的问题编译环境 我的demo是通过此文章从C更改成的C&#xff0c;编译环境使用的是Mingw&#xff0c;如下图所示 快速入门 拷贝代码编译互传消息 编译指令 客户端&#xff1a;gcc .\udpclient.c -lwsock3…

《剑指offer》– 链表中倒数第k个节点、反转链表、合并两个排序的链表

一、链表中倒数时第k个节点&#xff1a; 1、题目&#xff1a; 输入一个链表&#xff0c;输出该链表中倒数第k个结点。 2、解题思路&#xff1a;单链表具有单向移动的特性。 &#xff08;1&#xff09;第一种&#xff1a;先遍历链表&#xff0c;算出链表节点数count&#xf…

计算机毕设Python+Vue学生用品采购系统(程序+LW+部署)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

我国风电行业发展现状:并网装机容量持续增长 产业集中化趋势明显

根据观研报告网发布的《2022年中国风电行业分析报告-行业全景评估与投资规划分析》显示&#xff0c;风电是一种清洁、绿色的可再生能源。风力发电是能源领域中技术最成熟、最具规模开发条件和商业化发展前景的发电方式之一。发展风力发电对于解决能源危机、减轻环境污染、调整能…

【Java面试八股文宝典之基础篇】备战2023 查缺补漏 你越早准备 越早成功!!!——Day13

大家好&#xff0c;我是陶然同学&#xff0c;软件工程大三明年实习。认识我的朋友们知道&#xff0c;我是科班出身&#xff0c;学的还行&#xff0c;但是对面试掌握不够&#xff0c;所以我将用这100多天更新Java面试题&#x1f643;&#x1f643;。 不敢苟同&#xff0c;相信大…

【1760. 袋子里最少数目的球】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 给你一个整数数组 nums &#xff0c;其中 nums[i] 表示第 i 个袋子里球的数目。同时给你一个整数 maxOperations 。 你可以进行如下操作至多 maxOperations 次&#xff1a; 选择任意一个袋子&#…

开发板到货记录一波

今天在终于拿到了期待已久的开发板RK3568&#xff0c;来&#xff0c;亮个相吧&#xff01;&#xff01;&#xff01; 开发板资源还是相当丰富的&#xff0c;对于学习安卓&Linux都是非常友好的&#xff0c;开发板默认安装的是安卓11系统&#xff0c;由于经费问题目前还没有…

小米发明“永动机”:走路即可为智能设备充电

蓝牙耳机、智能智能手表、智能手环、智能眼镜、智能手机……随着科技的进步&#xff0c;越来越多的移动与可穿戴智能设备开始走进我们的生活&#xff0c;智能设备在给人们生活带来便利的同时&#xff0c;也带来了一些困惑&#xff0c;越来越多诸如手环、TWS耳机等智能穿戴设备&…

火热的元宇宙,成为未来趋势

近年来&#xff0c;中国在算力上突飞猛进&#xff0c;有望成为世界顶尖&#xff0c;再加数据和算法上的优势&#xff0c;中国就很有可能在元宇宙方面率先开发出原创性的技术&#xff0c;从而实现从“0”到“1”的突破。 元宇宙办公 在未来的元宇宙畅想中&#xff0c;人们不仅…

java Lambda表达式的标准格式及其前提带有(代码演示)

观看本文 首先 你要对Lambda的概念有个基本了解 对此 您可以先查看我的文章 java Lambda概念 通过实现线程简单体验一下Lambda表达式 跟着上一篇文章做 你的代码会是这样 new Thread( () ->{System.out.println("执行线程"); } ).start();而其中Lambda 表达式 则…

资产种类多数量大、使用地点分散?集中管理,一招搞定

随着银行规模不断壮大&#xff0c;资产数量也随之不断增加&#xff0c;同时银行资产具有总量大、价值高、使用地点分散、管理难度大的特点&#xff0c;IT资产、房产、办公用品、维修保养需求随着业务的快速增长对管理工作带来了压力。 传统资产管理4大痛点 01.账实不符 实物账…

【Python机器学习】神经网络中常用激活函数、损失函数、优化方法(图文解释 附源码)

下面以经典的分类任务&#xff1a;MNIST手写数字识别&#xff0c;采用全连接层神经网络 MNIST数据集是一个手写体的数字图片集&#xff0c;它包含有训练集和测试集&#xff0c;由250个人手写的数字构成。训练集包含60000个样本&#xff0c;测试集包含10000个样本。每个样本包括…

数据结构基础--散列表

一、散列简介 散列表&#xff0c;又叫哈希表&#xff08;Hash Table&#xff09;&#xff0c;是能够通过给定的关键字的值直接访问到具体对应的值的一个数据结构。也就是说&#xff0c;把关键字映射到一个表中的位置来直接访问记录&#xff0c;以加快访问速度。 通常&#xff0…

Android设计模式详解之建造者模式

前言 Builder模式是一种创建型设计模式。 定义&#xff1a;将一个复杂对象的创建与它的表示分离&#xff0c;使得同样的构造过程可以创建不同的表示。 使用场景&#xff1a; 相同的方法&#xff0c;不同的执行顺序&#xff0c;产生不同的事件结果时&#xff1b;多个部件或零…

java学习day63(乐友商城)商品新增后台、商品编辑后台、搭建前台系统页面

1.商品新增 当我们点击新增商品按钮&#xff1a; 就会出现一个弹窗&#xff1a; 里面把商品的数据分为了4部分来填写&#xff1a; 基本信息&#xff1a;主要是一些简单的文本数据&#xff0c;包含了SPU和SpuDetail的部分数据&#xff0c;如 商品分类&#xff1a;是SPU中的cid1&…

大型项目都会使用到的Makefile

一、vi编辑器之神 1.vi编辑器的三种模式&#xff1a; 插入模式&#xff1a;可以编辑文档 编辑模式&#xff1a;可以敲一些命令&#xff0c;执行例如复制n行 剪切n行 &#xff0c;粘贴等功能 命令模式:(最后一行模式&#xff09; 在此模式下可以保存文件&#xff0c;退出vi…

第03讲:Redis的持久化方案

前言 redis是一个内存数据库&#xff0c;当redis服务器重启&#xff0c;获取电脑重启&#xff0c;数据会丢失&#xff0c;我们可以将redis内存中的数据持久化保存到硬盘的文件中。 redis提供两种持久化方式: RDB&#xff1a;快照&#xff0c;通过从服务器保存和持久化AOF&…

Codeforces Round #839 (Div. 3) A~G all answer

Dashboard - Codeforces Round #839 (Div. 3) - Codeforces 最近状态奇差无比&#xff0c;还有点生病&#xff0c;低烧反复横跳&#xff0c;应该没阳&#xff1f;&#xff08;虽然家人都阳了&#xff0c;就剩我一个了wuwuwu&#xff5e;&#xff08;A B C就不作解释了&#xff…