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

news/2024/4/27 9:49:40/文章来源:https://blog.csdn.net/phantom_111/article/details/130340350

1. 写在最前面

「利用输出,来倒逼自己学习,大概是倦怠期最好的解决方法了吧」,最近查的问题有点多,每天略显心力交瘁,学习新知识的速度要提升呀。

查问题小心得,如果发现一个问题,在多个客户的使用中被反复提及,请务必提高警惕,这个问题即为—「产品设计的不合理的体现」。

注:研发大量的人肉运维,始终不如发现根因后,修复产品设计的方法,更能提高用户的使用满意度

警惕大量的「重复体力劳动」,让自己丧失深入思考的动力!

2. 元语言抽象

专业程序员在设法控制他们的设计的复杂性时,采用的正是与所有复杂系统的设计者同样的通用技术。将基本元素组合起来,形成复合元素,从复合元素出发通过抽象形成更高一层的构件,保持系统的模块性。

注:建立新语言是在工程设计中控制复杂性的一种威力强大的工作策略,常常能通过采用一种新语言而提升处理复杂问题的能力,因为新语言可能是我们一种完全不同的方式,利用不同的原语,不同的组合方式和抽象方式去描述所面对的问题。

元语言抽象就是建立新的语言。它在工程设计的所有分支中都扮演着重要的角色,在计算机程序设计领域更是特别重要,因为这个领域中,我们不仅可以设计新的语言,还可以通过构造求值器的方式实现这些语言。

注:求值器决定了一个程序设计语言中各种表达式的意义,而它本身也不过就是另一个程序。

    处理大规模计算机系统的技术,与构造新的程序设计语言的技术有紧密的联系,而计算机科学本身不过就是有关如何构造适当的描述语言的学科。

在这一章里,我们将用 Lisp 语言作为基础,将各种求值器实现为一些 Lisp 过程。

3. 元循环求值器

「用与被求值的语言同样的语言写出的求值器被称为元循环」,从根本上来说,元循环求值器也就是 3.2 节所描述的求值的环境模型的一个 Scheme 表达形式,该模型包括两个部分:

  • 在求值一个组合式时,首先求值其中的子表达式,而后将运算符子表达式的值作用于运算对象子表达式的值

  • 在将一个复合过程应用于实际参数时,我们在一个新的环境里求值这个过程的体。构造这一环境的方式就是用一个框架扩充该过程对象的环境部分,框架中包含的是这个过程的各个形式参数与这一过程应用的各个实际参数的约束

这两条规则描述了求值的核心部分,也就是它的基本循环。这一求值循环实际体现为求值器里的两个关键过程 eval 和 apply 的相互作用。

3.1 求值器的内核

eval

eval 的参数是一个表达式和一个环境。eval 对表达式进行分类,依此引导自己的求值工作。

注:eval 的构造就像是一个针对被求值表达式的语法类型的分情况分析。

apply

apply 有两个参数,一个是过程,一个是该过程应该去应用的实际参数的表。apply 将过程分为两类。它直接调用 apply-primitive-proceduce 去应用基本过程,应用复合过程的方式是顺序地求值组成该过程体的那些表达式。

过程参数

eval 在处理过程应用时用 list-of-values 去生成实际参数表,以便完成这一过程应用。

条件

eval-if 在给定环境中求值 if 表达式的谓词部分,如果得到的结果为真,eval-if 就去求值这个 if 的推论部分,否则它就求值其替代部分。

序列

eval-sequence 用在 apply 里,用于求值过程体力的表达式序列。

赋值和定义

下面过程处理变量赋值。它调用 eval 找出需要赋的值,将变量和得到的值传给过程 set-variable-value!,将有关的值安置在指定的环境里。

3.2 表达式的表示

这两个程序完成的都是一些对符号表达式的操作。

  • 在两个程序里,对于一个复合表达式的操作结果,也都是由表达式的片段递归地确定的,结果的组合也是按照一种由表达式的类型确定的方式。

  • 在这两个程序里,我们都采用了数据抽象技术,借以解耦一般性的操作规则与表达式特定表示的细节方式之间的联系。

例子:

  • 在微分程序里,这意味着同一个微分过程可以处理前缀形式、中缀形式,或者其他形式的代数表达式

  • 对于求值器,这意味着,被求值语言的语法形式可以仅仅由一些对表达式进行分类和提取表达式片段的过程确定

派生表达式

一些特殊形式可以基于其他特殊形式的表达式定义出来,而不必直接去实现。一个这样的例子是 cond,它可以实现为一些嵌套的 if 表达式。举例来说,我们可以将对于下述表达式的求值问题:

(cond ((> x 0) x)((= x 0) (display 'zero) 0)(else (- x)))

归约为对下面涉及 if 和 begin 的表达式的求值问题:

(if (> x 0)x(if (= x 0)(begin (display 'zero)0)(- x)))

采用这种方式实现去 cond 的求值能简化求值器,因为这样就减少了需要特别描述求值过程的特殊形式的数目。

3.3 求值器数结构

除了需要定义表达式的外部语法形式之外,求值器的实现还必须定义好在其内部实际操作的数据结构,作为程序执行的一部分。例如,定义好过程和环境的表示形式,真和假的表示方式等等。

谓词检测:为了实现条件表达式,我们把除了 false 对象之外的所有东西都接受为真

过程的表示: 为能处理基本过程,我们假定已经有了下述过程:

  • (apply-primitive-procedure <proc> <args>)它将给定的过程应用于表 <args> 里的参数值,并返回这一应用的结果。

  • (primitive-procedure ? <proc>)检查 <proc> 是否为一个基本过程

对环境的操作:求值器需要一个对环境的操作,一个环境就是一个框架的序列,每个框架都是一个约束的表格,其中的约束关联起一些变量和与之对应的值。

注:本章所描述的方法,只不过是表示环境的许多可能方法之一。由于前面采用了数据抽象技术,将求值器的其他部分与这些表示细节隔离开,如果需要的话,我们也完全可以修改环境表示。

3.4 作为程序运行求值器

将求值器描述为程序的一个优点是我们可以运行这个程序,这样就给了我们一个能够在 Lisp 里运行的,有关 Lisp 本身如何完成表达式求值的工作模型。这一模型可以作为一个工作框架,使人能够去试验各种求值规则。

注:求值器程序最终将把表达式归约到基本过程的应用。

每个基本过程名必须有个约束,以便当 eval 求值一个应用基本过程的运算符时,可以找到相应的对象,并将这个对象传给 apply。为此我们必须创建一个初始环境,在其中建立起基本过程的名字与一个唯一对象的关联,在求值表达式的过程中可能遇到这些名字。

注:这一全局环境里还要包含符号 true 和 false 的约束,这就使它们也可以作为变量用在被求值的表达式里。

(define (setup-environment)(let ((initial-env(extend-environment (primitive-procedure-names)(primitive-procedure-objects)the-empty-environment)))(define-varibale! 'true true initial-env)(define-varibale! 'false false initial-env)initial-env))
(define the-global-environment (setup-environment))

注:基本过程对象的具体表示并不重要,只要 apply 能识别它们,并能通过过程 primitive-procedure? 和 apply-primitive-procedure 去应用它们。

3.5 将数据作为程序

在思考求值 Lisp 表达式的 Lsip 程序时,有一个类比可能很有帮助。关于程序意义的一种操作观点,就是将程序看成一种抽象的(可能无穷大的)机器的一个描述。例如,考虑下面这个已经非常熟悉的求阶乘程序:

(define  (factorial n)(if (= n 1)1(* (factorial (- n 1)) n )))

求值器的另一惊人方面,在于它就像是在我们的程序设计语言所操作的数据对象和这个程序设计语言本身之间的一座桥梁。

现在设想这个求值程序正在运行,一个用户正在输入表达式并观察所得到的结果。

  • 从用户的观点看,他所输入的形如(* x x)的表达式是程序设计语言里的一个表达式,是求值器将要执行的东西。

  • 而从求值器的观点看,这一表达式不过是一个表(在目前的情况下,是三个符号 *、x 和 x 的表),它所要去做得,也就是按照一套良好的规则去操作这个表。

3.6 内部定义

求值和元循环求值器的环境模型将按顺序执行给它的定义,一次在环境框架里扩充一个定义。对于交互式的程序开发,这样做事特别方便的,因为程序员需要自由地混合过程应用和新过程的定义。

注:但是用于实现块结构的内部定义,就会发现,这种一次一个名字的环境扩充方式可能不是定义局部变量的最好方式。

考虑如下一个带有内部定义的过程:

(define (f x)(define (even? n)(if (= n 0)true(odd? (- n 1))))(define (odd? n)(if (= n 0)false(even? (- n 1)))
<f 体的其余部分>)

在这里的意图是,在过程 even? 的体里的名字 odd? 应该引用过程 odd?,而它是在 even? 之后定义的。名字 odd? 的作用域是 f 的整个体,而不仅是 f 的体里从出现 odd?的 define 点开始的那个部分。确实,在我们考虑 odd?本身也是基于 even? 定义的时候——所以 even? 和 odd? 是相互递归定义的过程——就可以看到。

注:有关这两个 define 的最令人满意的解释,应该是认为两个名字 even? 和 odd? 被同时加入环境中。

总结,在块结构里,一个局部名字的作用域,应该是相应 define 的求值所在的整个过程体。

事实上,只要过程里的内部定义出现在体和用于定义变量的值表达式的求值之前,而这些值表达式又不实际使用任何被定义变量,顺序求值机制给出的结果就与直接实现同时定义完全一样。

3.7 将语法分析与执行分离

上述实现的求值器确实很简单,但却也非常低效,因为有关表达式的语法分析与它们的执行交织在一起。如果一个程序要执行很多次,对于它的语法分析也就需要做许多次。

可以对求值器做一些变换,使其效率大大提高,采用的方法就是重新安排其中的工作,使有关的语法分析只进行一次。

  • 要将以一个表达式和一个环境为参数的 eval 分割为两个部分

  • 过程 analyze 只取表达式作为参数,它执行语法分析,并返回一个新的过程,执行过程,其中封装起在分析表达式的过程中已经完成的工作。

将语法分析和执行分开之后,eval 现在就变成了

(define (eval exp env)((analyze exp) env ))

调用 analyze 的结果得到一个执行过程,而后将它应用于环境。analyze 过程完成 3.1 里 eval 那样的分情况分析,除了其中的分派过程只执行分析工作,不进行完全的求值:

(define (analyze exp)(cond ((self-evaluating? exp)(analyze-self-evaluating exp))((quoted? exp) (analyze-quoted exp))((variable? exp) (analyze-variable exp))((assignment? exp) (analyze-assignment exp))((definition? exp) (analyze-definition exp))((if? exp) (analyze-if exp))((lambda? exp) (analyze-lambda exp))((begin? exp) (analyze-sequence (begin-ations exp)))((cond? exp) (analyze (cond->if exp)))((appliction? exp) (analyze-appliction exp))(else(error "Unknown expression type -- ANALYZE" exp))))

下面是一个处理自求值表达式的简单分析过程,它返回一个忽略环境参数的执行过程,直接返回相应的表达式:

(define (analyze-self-evaluation exp)(lambda (env) exp))

4. 碎碎念

断断续续的才把整理某一小节的文章写完,看来周末加班真的会降低生产力。

发现快三十岁的自己,还是没办法很好的控制情绪。听到要好小伙伴离职的消息,依然会不顾他人诧异的目光,在路上就开始流眼泪。但是那又有什么关系呢?大概所有人终其一生,都在和自己和解吧。

  • 既然相遇是偶然,又何必在意分别时的突然呢?

  • 太敏感了,被小小忽略一下,就能闷闷不乐一整天。

  • 请你要发光,而不是被照亮。

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

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

jenkins自动化部署配置

文章目录 1. jenkins 插件安装2. 配置2.1 全局工具配置2.2 全局配置2.2.1 gitee 配置 3. 创建任务添加gitee ssh jenkins 开机自启动 1. jenkins 插件安装 ant Build Failure AnalyzerBuild Monitor ViewBuild Timeout dockerEmail Extension Plugin giteegithubgradle javama…

Python科研数据可视化

在过去的20 年中&#xff0c;随着社会产生数据的大量增加&#xff0c;对数据的理解、解释与决策的需求也随之增加。而固定不变是人类本身&#xff0c;所以我们的大脑必须学会理解这些日益增加的数据信息。所谓“一图胜千言”&#xff0c;对于数量、规模与复杂性不断增加的数据&…

广域通信网 - 流量控制(停等协议、滑动窗口协议)

文章目录 1 概述2 流量控制协议2.1 停等协议2.2 滑动窗口协议 1 概述 #mermaid-svg-c9cNIYsOvLpoO4AV {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-c9cNIYsOvLpoO4AV .error-icon{fill:#552222;}#mermaid-svg-c9c…

跳槽必备,全面总结Android面试知识点

在最近的 Android 开发&#xff08;社招&#xff09;面试中总结的 Android 基础知识点&#xff0c;已经拿到心仪的offer&#xff0c;回馈同学们&#xff0c;感谢其他大佬的分享。 Android中大厂面试都很重视基础知识的考察&#xff0c;面试前不仅要熟悉这些知识点&#xff0c;…

设计模式之访问者模式(C++)

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 一、访问者模式是什么&#xff1f; 访问者模式是一种行为型的软件设计模式&#xff0c;表示一个作用于某对象结构中的各元素的操作…

智能家居代码架构---简单工厂模式

(11条消息) 智能家居 (10) ——人脸识别祥云平台编程使用(编译libcurl库支持SSL&#xff0c;安装SSL依赖库libssl、libcrypto)openssl 依赖库行稳方能走远的博客-CSDN博客 看上面这个博客的往期文章 代码设计经验的总结&#xff0c;稳定&#xff0c;拓展性更强。一系列编程思…

DAX:概述ALL函数

简单的说&#xff0c;当ALL用作表函数时&#xff0c;忽略应用到表上的任何过滤器&#xff0c;并返回数据表&#xff1b;当ALL用作CALCULATE和CALCULATETABLE函数中修饰器时&#xff0c;ALL函数从扩展表中移除已经应用的过滤上下文。 注意自动存在(auto-eixist)对ALL()函数的影响…

选址-路径问题(Location-Routing Problem, LRP)

今天为大家介绍的是选址-路径问题(Location-Routing Problem, LRP)&#xff0c;首先上目录 目录 问题简介 基础模型、扩展问题及应用 算法 参考文献 1 问题简介 为了更好地了解这个问题&#xff0c;我们不妨当一波老板。 想象一下我们是经营一家口罩生产企业的老板&am…

案例——数据表的基本操作

目录 案例目的&#xff1a; 创建表&#xff1a; 创建offices&#xff1a; 创建employees表&#xff1a; 修改表&#xff1a; 将 employees 的 mobile 字段移动到 officeCode 字段后&#xff1a; 将 birth 字段名称改为 employee_birth: 修改 sex 字段&#xff0c;数据类…

Vue的路由实现:hash模式 和 history模式原理及区别

目录标题 1、hash模式2、history模式 Vue-Router有两种模式: ** hash 模式和 history**模式。默认的路由模式是hash模式。 1、hash模式 简介&#xff1a;hash模式是开发中默认的模式&#xff0c;它的URL带着一个#&#xff0c;例如:http://www.abc.com/#/vue&#xff0c;它的…

Facebook、Google、亚马逊,谁将成为跨境电商的营销宠儿?

跨境电商在全球范围内的发展日益迅猛&#xff0c;而营销渠道的选择也变得越来越多样化。在众多的广告平台中&#xff0c;Facebook、Google和亚马逊被公认为是跨境电商卖家们最主要的营销平台。那么&#xff0c;这三个平台中哪个会成为跨境电商的营销宠儿呢&#xff1f; 一、Fac…

【GIT】git push后长时间没反应

方向一 查看是否添加ssh 打开git bash cd ~/.ssh看是否成功&#xff0c;能成功说明之前生成过&#xff0c;看文件夹下是否有id_rsa.pub和id_rsa文件&#xff0c;有的话跳过生成步骤3 输入 ssh-keygen -t rsa -C ‘your_emailexample.com’(注&#xff1a;your_emailexample.c…

二百左右的蓝牙耳机哪款好?200左右音质最好的蓝牙耳机

在日常生活中离不开智能手机&#xff0c;特别是对无线蓝牙耳机的需求程度也越来越高&#xff0c;但是市面上有很多的蓝牙耳机戴久了耳朵会出现不舒服&#xff0c;为了获得更好的使用体验&#xff0c;我整理了市面上200左右价位佩戴和音质都表现不错的蓝牙耳机。 一、南卡小音舱…

“SCSA-T学习导图+”系列:IPSec VPN原理与应用

本期引言&#xff1a; 本章主要讲解IPSec VPN相关理论概念&#xff0c;工作原理。从安全和加密原理入手&#xff0c;讲解了IPSec 在VPN对等体设备实现的安全特性&#xff0c;如数据的机密性、数据的完整性&#xff0c;数据验证等。重点分析IPSec封装模式&#xff0c;IPSec安全…

【HDCTF2023】wp

【HDCTF2023】wp 文章目录 【HDCTF2023】wpwebWelcome To HDCTF 2023SearchMasterYamiYamiLoginMaster mischardMiscMasterMiscExtremeMiscSuperMisc web Welcome To HDCTF 2023 在源码的 game.js中找到了flag 在控制台输出 console.log(seeeeeeeecret)得flag SearchMaster …

亚马逊美国站带绳窗帘

带绳窗帘 如果您在亚马逊商城发布商品&#xff0c;则必须遵守适用于这些商品和商品信息的所有联邦、州和地方法律以及亚马逊政策&#xff08;包括本政策&#xff09;。 本政策涵盖的带绳窗帘 带绳窗帘是一种室内用窗帘&#xff0c;可通过一根吊绳控制升降。此类商品包括但不…

【PR 基础】轨道遮罩键、交叉溶解的简单使用

在上篇博客&#xff08;【PR 基础】裁剪工具的简单使用&#xff09;介绍了裁剪效果的使用&#xff0c;本篇博客在上篇的基础上继续添加 轨道遮罩键、交叉溶解的效果。 效果 步骤 1.可以先将恢复裁剪区域的关键帧删除 2. 接下来添加字幕&#xff0c;点击 新建-》旧版标题 点击…

vue3+ts+pinia+vite一次性全搞懂

vue3tspiniavite项目 一&#xff1a;新建一个vue3ts的项目二&#xff1a;安装一些依赖三&#xff1a;pinia介绍、安装、使用介绍pinia页面使用pinia修改pinia中的值 四&#xff1a;typescript的使用类型初识枚举 一&#xff1a;新建一个vue3ts的项目 前提是所处vue环境为vue3&…

flask学习-实践02

项目实战 入门文当(2条消息) python flask框架详解_flask python_尘世风的博客-CSDN博客(2条消息) python flask框架详解_flask python_尘世风的博客-CSDN博客 入门项目 抄作业了&#xff01;6 大 Flask 开源实战项目推荐_小詹学 Python的博客-CSDN博客 (66 条消息) GitHub 上有…

Transformer 位置编码代码解析

Transformer 位置编码代码解析 Transformer 的 Multi-Head-Attention 无法判断各个编码的位置信息。因此 Attention is all you need 中加入三角函数位置编码&#xff08;sinusoidal position embedding&#xff09;&#xff0c;表达形式为&#xff1a; P E ( p o s , 2 i ) …