计算机程序的构造和解释

 

 

 

创建一个有理数

(define (make-rat n d) (cons n d))      #定义一个分数

(define (number x) (car x))                 #number获取一个分数的分子部分

(define (denom x) (cdr x))                  #denom获取一个分数的分母部分

 

打印有理数

(define (print x)

(newline)                           #内置的基本过程,打印新的一行

(display (number x))        #打印分子部分

(display "/")                       #打印 /

(display (denom x))         #打印分母部分

 

#定义一个分数

(define one-half (make-rat 1 2))

one-half

(1 . 2)

(print one-half)                 #打印分数

 

1/2

 

 

 

可以执行加减乘除运算的 解释器

#lang racket
(define (calc exp)
   (match exp                                ; 匹配表达式的两种情况
     ((? number? x) x)                       ; 是数字,直接返回
     (`(,op ,e1 ,e2)                         ; 匹配并且提取出操作符 op 和两个操作数 e1, e2
      (let ((v1 (calc e1))                   ; 递归调用 calc 自己,得到 e1 的值
            (v2 (calc e2)))                  ; 递归调用 calc 自己,得到 e2 的值
        (match op                            ; 分支:处理操作符 op 的 4 种情况
          (`+ (+ v1 v2))                     ; 如果是加号,输出结果为 (+ v1 v2)
          (`- (- v1 v2))                     ; 如果是减号,乘号,除号,相似的处理
          (`* (* v1 v2))
          (`/ (/ v1 v2)))
        );end let
      );end (`(,op,e1,e2)
     );end match
  );end define

( calc '(+ ( + 1 2)  ( + 3 4)) )

 

定义了calc这个函数,同时也使用到了模式匹配的功能

`(op,e1,e2) 表示当前的数据结构中有三个元素,所以匹配(op,e1,e2)这三个元素

let是赋值并执行一段内容

(let (v1 值) (v2 值) (....)  (body 执行一段内容) )

这段的作用是如果匹配的是数字就返回,否则递归的求e1和e2的值,当求解完后将他们分别赋给e1和e2

最后还有一个match用于匹配op的,匹配到 加减乘法再做对应的运算 

 

 

 

#lang racket
(define env0 '())

;; 扩展。对环境 env 进行扩展,把 x 映射到 v,得到一个新的环境
(define ext-env
 (lambda (x v env)
   (cons (cons x v) env)))

;; 查找。在环境中 env 中查找 x 的值
(define lookup
            (lambda (x env)
            (let ([p (assq x env)])
               (cond
                  [(not p) x]
                    [else (cdr p)]))))

;; 闭包的数据结构定义,包含一个函数定义 f 和它定义时所在的环境
(struct Closure (f env))

;; 解释器的递归定义(接受两个参数,表达式 exp 和环境 env)
;; 共 5 种情况(变量,函数,调用,数字,算术表达式)
(define interp1
 (lambda (exp env)
   (match exp                                          ; 模式匹配 exp 的以下情况(分支)
     [(? symbol? x) (lookup x env)]                    ; 变量
     [(? number? x) x]                                 ; 数字
     [`(lambda (,x) ,e)                                ; 函数
      (Closure exp env)]
     [`(,e1 ,e2)                                       ; 调用
      (let ([v1 (interp1 e1 env)]
            [v2 (interp1 e2 env)])
        (match v1
          [(Closure `(lambda (,x) ,e) env1)
           (interp1 e (ext-env x v2 env1))]))]
     [`(,op ,e1 ,e2)                                   ; 算术表达式
      (let ([v1 (interp1 e1 env)]
            [v2 (interp1 e2 env)])
        (match op
          [‘+ (+ v1 v2)]
          [‘- (- v1 v2)]
          [‘* (* v1 v2)]
          [‘/ (/ v1 v2)]))])))


(define (interp exp)
  (interp1 exp env0)
)

(interp '(((lambda (x) (lambda (y) (* x y))) 2) 3)) 

下面表达式的计算过程

(interp '( (lambda(xx) (+ 1 xx)) 10 ) )

 

调用到match中的判断

(`(,e1 ,e2) 

这里的e1是  (lambda (xx) (+ 1 xx))

e2是  10

 

(`(,e1 ,e2))中的递归计算

[v1 (interp1 e1 env)]

[v2 (interp1 e2 env)]

 

其中 [v1 (interp1 e1 env)]

会调用到match中的判断

(`(lambda (,x) ,e) 

这里的x是 lambda函数的参数xx

e 是函数内的表达式 (+ 1 xx)

 

之后 [v2 (interp1 e2 env)]

会调用到

[(? number? x) x] 

 

之后执行到mathc v1

        (match v1

          [(Closure `(lambda (,x) ,e) env1)

           (interp1 e (ext-env x v2 env1))])

 

(interp1 e (ext-env x v2 env1))

这段的作用是计算表达式

e的值是    (+ 1 xx)

x的值是    函数的参数xx

v2的值是   10

env1的值是 ()    

(ext-env x v2 env1)

这段的作用是将

lambda的参数x(传入的参数名叫xx),还有值v2(内容是10)加入到env1环境中

此时env1是() 空的,所以执行完后env1就是(xx 10)

(+ 1 xx) ext-env最后匹配到 [`(,op ,e1 ,e2)

op是+

e1是 1

e2是xx,然后匹配到表达式 [(? symbol? x) (lookup x env)]

返回xx的值也就是10

最后计算表达式(+ 1 10) 结果为11

 

------------------------------------------------------------------------------------------------------------

 

下面表达式的计算过程

(interp '(((lambda (x) (lambda (y) (* x y))) 2) 3))

 

首先[`(,e1 ,e2)被匹配上

(let ([v1 (interp1 e1 env)]

递归执行这里的e1是

((lambda (x) (lambda (y) (* x y))) 2)

 

[v2 (interp1 e2 env)]

这里的e2是数字 3

然后匹配到 [(? number? x) x] 直接返回数字3

 

 

[v1 (interp1 e1 env)会递归调用解释器函数,最后匹配到这里

['(lambda (,x) ,e)

  (Closure exp env)]

Closure中的的exp为

    '(lambda (x) (lambda (y) (* x y)))

env为 '()

 

match匹配v1然后

(interp1 e (ext-env x v2 env1))

这里的 e是

    (lambda (y) (* x y))

x是lambda(y)中的参数y,这个表达式相当于

(interp1 '(lambda(y) (* x y)) ext-env)

这里的ext-env相当于 (x 2)

 

于是 (interp1 '(lambda(y) (* x y)) ext-env)

会继续递归,调用到[`(,e1 ,e2)

最后变成 (interp1 (* x y) ext-env)

这里的ext-env是((y 2) (x 3))

 

 

最后执行到 [`(,op ,e1 ,e2) 

这里的op 是*

e1 是 x

e2 是 y

x和y是变量,也就是匹配到表达式

[(? symbol? x) (lookup x env)] 

调用lookup函数查找key对应的value,结果x就是3,y就是2

而op匹配到 *,执行 (* 3 2)结果就是6 

 

 

 

 

 

schema官方列表

kawa官方文档

Racket官方文档

SCIP公开课翻译项目

麻省理工SCIP公开课主页

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1,过程作为返回值 在1.3中我们明白了高阶函数之后,“用一个过程作为另外一个过程的返回值”则是稀松平常的事情了,比如下面的代码: (define (f x) (+ x 1)) (define (g) f) ((g) 2) 函数g没有参数,其返回值为函数f,所以((g) 2)就运算结果就是(f 2),最后运算结果为3。 上面是用一个已命名的函数作为返回结果的,相应的,也可以将一个“匿名过程”作为结果返回,这里的“匿名过程”也就是我们的Lambda表达式,所以上面的代码可以改造成: (define (g) (lambda (x) (+ x 1))) ((g) 2) 那么((g) 2)的运算结果就是((lambda (x) (+ x 1)) 2),最后运算结果为3。 2,牛顿法 学到这里,你可能需要复习一下高等数学的基本内容,包括“导数”和“微分”,高数的在线教材可以在这里找到:http://sxyd.sdut.edu.cn/gaoshu1/index.htm 关于牛顿法的介绍可以看这里:http://en.wikipedia.org/wiki/Newton%27s_method ,下面是程序: (define (close-enough? v1 v2) (< (abs (- v1 v2)) 0.000000001)) ;定义不动点函数 (define (fixed-point f first-guess) (define (try guess step-count) (let ((next (f guess))) (if (close-enough? guess next) next (try next (+ step-count 1))))) (try first-guess 0)) ;定义导数函数 (define (D f) (lambda (x dx) (/ (- (f (+ x dx)) (f x)) dx))) ;牛顿法 (define (newton g first-guess) (fixed-point (lambda (x) (- x (/ (g x) ((D g) x 0.000000001)))) first-guess)) ;平方 (define (square x) (* x x)) ;定义开方,来测试下牛顿法 (define (sq x) (newton (lambda (y) (- (square y) x)) 1.0)) (sq 5) 3,“一等公民” 这里列出了程序语言中作为“一等公民”的语言元素所具备的几个“特权”: 可以用变量命名 可以作为过程参数 可以作为过程返回结果 可以被包含在数据结构中 4,练习1.40 求三次方程 x^3 + ax^2 + bx + c 的零点。 首先,证明 函数f(x) = x^3 + ax^2 + bx + c 是“可微”的: 由可导和可微的性质知道,可导和可微互为充要条件,所以,要证可微我们可以先证可导, f ’ (x) = (x^3)’ + (ax^2)’ + (bx)’ + (c)’ = 3x^2 + 2ax + b 所以f(x)的导数存在,那么f(x)可导,其必定可微。 其次,利用“牛顿法”:如果f(x)是可微函数,那么f(x)=0的一个解就是函数(x – f(x)/df(x)的一个不动点,其中df(x)是f(x)的导数。所以我们可以轻松得到下面的代码: (define (close-enough? v1 v2) (< (abs (- v1 v2)) 0.000000001)) ;定义不动点函数 (define (fixed-point f first-guess) (define (try guess step-count) (let ((next (f guess))) (if (close-enough? guess next) next (try next (+ step-count 1))))) (try first-guess 0)) ;定义导数函数 (define (D f) (lambda (x dx) (/ (- (f (+ x dx)) (f x)) dx))) ;牛顿法 (define (newton g first-guess) (fixed-point (lambda (x) (- x (/ (g x) ((D g) x 0.000000001)))) first-guess)) ;定义cubic函数,也就是我们题目中所谓的f(x) (define (cubic a b c) (lambda (x) (+ (* x x x) (* a x x) (* b x) c))) ;随便定义几个系数 (define a 3) (define b 5) (define c 8) (define result (newton (cubic a b c) 1.0)) ;定义一个验证过程,让其验证得到的解,是否让方程成立 (define (validate x) (= 0 (+ (* x x x) (* a x x) (* b x) c))) ;输出结果 result ;验证结果 (validate result) 比如上面我们计算 x^3 + 3x^2 + 5x + 8 = 0, 其一个解为:-2.3282688556686084 .....
### 回答1: 《计算机程序构造解释》是一本经典的计算机科学教材,它由Harold Abelson和Gerald Jay Sussman创作,已经成为计算机科学领域的里程碑之一。该教材于1979年首次出版,最新版是第二版。 该书的主要内容包括两个方面:计算机程序构造解释。首先,它详细解释计算机程序构造,强调了程序的基本要素和组织原则。这可以帮助读者理解如何使用编程语言和工具构建高效和可靠的计算机程序。书中还介绍了一些常见的编程范式和设计模式,如函数式编程和面向对象编程,使读者能够选择适合自己项目的最佳方法。 其次,该书解释计算机程序解释过程。它介绍了一种称为Lisp的编程语言,这是一种函数式编程语言,非常适合表达和解释复杂的计算机程序。通过详细讲解Lisp的语法和语义,读者可以深入了解程序如何被计算机解释和执行。这对于理解计算机底层工作原理和实现高性能程序非常有帮助。 《计算机程序构造解释》被广泛认为是计算机科学入门的必读教材。它不仅适合计算机科学专业的学生学习,也适合对计算机程序有兴趣的非专业读者。该书的内容深入浅出,兼具理论和实践,读者可以通过阅读本书并进行相应的练习来提高他们的编程能力和计算机科学理解。 总之,《计算机程序构造解释》是一本经典的计算机科学教材,它介绍了计算机程序构造解释两个重要方面。通过学习本书,读者可以掌握构建高效和可靠程序的技巧,并深入理解计算机程序的执行过程。这本书对于计算机科学专业学生以及对计算机程序感兴趣的非专业读者都是极其有价值的。 ### 回答2: 《计算机程序构造解释》(简称SICP)是一本经典的计算机科学教材,该书由麻省理工学院的编程语言专家哈罗德·艾布尔森(Harold Abelson)和吉拉迪·塞斯曼(Gerald Jay Sussman)共同编写。它在计算机科学领域具有重要的地位和影响力。 该书的主要内容围绕着计算机程序构造解释展开。它从一个通用的编程语言(Scheme)出发,通过讲解计算机程序的抽象、过程和数据的重要概念,帮助读者建立起正确的思维模式和编程方法。 SICP通过一系列的例子和习题,引导读者通过编程实践来加深对计算机程序的理解。它强调程序设计的原理、模块化、抽象和递归等重要思想,通过一步步的讲解和示例,帮助读者培养出优雅和高效的编程风格。 SICP的目标是让读者真正理解计算机程序的本质,并学会如何用一种简单而强大的编程语言来构建复杂的软件系统。它不仅仅是一本教科书,更是一部引导读者探索计算机科学本质的指南。 总的来说,《计算机程序构造解释》是一本重要的计算机科学经典教材,它的初版已经出版超过30年,至今仍然是计算机科学教育领域的重要参考书之一。阅读该书可以帮助读者真正理解计算机程序的本质和设计原则,提升编程能力和思维方式。 ### 回答3: 《计算机程序构造解释》(SICP)是一本经典的计算机科学教材,也是学习编程的重要参考书籍。 这本书以文学化的形式介绍了计算机程序是如何构造解释的。它通过简明易懂的语言和丰富的示例,向读者解释了编程语言的设计原则、计算过程的原理以及如何理解和构造复杂的程序。 SICP主要分为五个部分。第一部分介绍了程序设计的基本概念和过程抽象的重要性。第二部分介绍了数据抽象和高阶过程,帮助读者理解程序设计中的重要概念和方法。第三部分讨论了程序设计的不同风格和编程的复杂性。第四部分介绍了元语言解释器的实现,帮助读者理解编程语言的工作原理。第五部分则介绍了一些高级主题,如并发和非确定性计算。 这本书的独特之处在于它不仅仅教授编程语言的具体细节,更重要的是让读者理解程序设计的理念和基本原则。它培养了读者逻辑思维和问题解决能力,帮助他们成为更好的程序员。 对于那些想要深入理解计算机程序构造解释的人来说,这本书是一个不可或缺的工具。它挑战了读者的思维,让他们思考计算机程序的本质和原理。无论是初学者还是有经验的程序员,阅读《计算机程序构造解释》都会有所收获,成为更好的计算机科学家或工程师。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值