第六章 Shadows

1 是算术表达式吗

3 是算术表达式吗

是的

1+3 是算术表达式吗

是的

1+3×4 是算术表达式吗

当然是

cookie 是算术表达式吗

是啊,你需要来一块吗

e那么 3 ^ y + 5

是的

你来说说什么是算术表达式

我们这样描述
“对于这一章,算术表达式可以是atom原子(包括数),或者由+,×,或者^连接的两个算术表达式。”

(quote a) 是什么

a

(quote +) 是什么

原子+,而不是操作+

(quote ×) 代表什么

代表原子×,而不是操作×

(eq? (quote a) y) 是真还是假,其中y是a

(eq? x y) 是真还是假,其中x是a,y是a

者痛前边的那个问题一样。真。

(n + 3) 是算术表达式吗

不是啊,括号括着 n + 3。我们的算术定义没有提到括号。

我们可以认为(n + 3) 是算术表达式吗吗

可以,只要注意括号问题。(原文没看明白:Yes, if we keep in mind that the parentheses are not really there.)

那(n + 3)怎么称呼

称作(n + 3)的表达(representation)

为什么(n + 3) 是一个好的表达

因为
1.  (n + 3) 是一个 S-expression表达式,它可以作为函数参数
2.  它就像 n + 3

(numbered? x)是真还是假,其中x是 1

3 + 4 × 5 的表示是什么

(3 + (4 × 5))

(numbered? y) 是真还是假,其中y是(3 + (4 ^ 5))

(numbered? z) 是真还是假,其中z是(2 × sausage)

假,因为sausage不是一个数。

numbered?是什么

一个函数,查询一个算术表示是否只包含有在+,×,和^,及其后边的数。

写个 numbered?函数的框架试试

(define numbered?
  (lambda (aexp)
    (cond
      (_____ _____)
      (_____ _____)
      (_____ _____)
      (_____ _____))))

第一个查询是什么

(atom? aexp)

(eq? (car (cdr aexp)) (quote +))是什么

这是第二个查询

你能猜出来第三个查询吗

(eq? (car (cdr aexp)) (quote ×)),完全正确

那第四个查询呢

(eq? (car (cdr aexp)) (quote ^)),完全正确

我们还需要查询aexp吗

不需要了,我们可以用else把前一个查询替换掉

为什么我们查询算术表达式是四个,而不是两个。毕竟像(1 + 3)这样的算术表达式是lats(即原子构成的list表)

因为我们把(1 + 3)表达看作是lsit表组成的算术表达式,而不是它本身的那样。而且算术表达式可以是数,或者有算术表达式和+,×,或者^连接组成。

现在你能写出函数 numbered?吗

(define (atom? x)
  (and (not (null? x))
       (not (pair? x))))

(define numbered?
  (lambda (aexp)
    (cond
      ((atom? aexp) (number? aexp))
      ((eq? (car (cdr aexp)) (quote +)) ...)
      ((eq? (car (cdr aexp)) (quote ×)) ...)
      ((eq? (car (cdr aexp)) (quote ^)) ...))))

为什么当aexp是atom原子时查询(number? aexp)

因为我们想知道算术表达式中的原子是否是数

为什么我们需要知道是否aexp中+连接的东西是否是两个算术表达式

我们需要查找出来两个子表达式是否是numbered

第一个 subsexpression在哪儿

就是aexp的car

第二个 subsexpression在哪儿

就是aexp的cdr的cdr的car(即aexp的第三个成员)

所以我们需要查询什么

(numbered? (car aexp))和(numbered? (car (cdr (cdr aexp))))必须都是真。

第二个回答是什么

(and (numbered? (car aexp)) (numbered? (car (cdr (cdr aexp)))))

再试试写出函数 numbered?

(define (atom? x)
  (and (not (null? x))
       (not (pair? x))))

(define numbered?
  (lambda (aexp)
    (cond
      ((atom? aexp) (number? aexp))
      ((eq? (car (cdr aexp)) (quote +)) (and (numbered? (car aexp)) (numbered? (car (cdr (cdr aexp))))))
      ((eq? (car (cdr aexp)) (quote ×)) (and (numbered? (car aexp)) (numbered? (car (cdr (cdr aexp))))))
      ((eq? (car (cdr aexp)) (quote ^)) (and (numbered? (car aexp)) (numbered? (car (cdr (cdr aexp)))))))))

既然aexp已经被认为是算术表达式,我们可以把 numbered?写得更简单些

(define (atom? x)
  (and (not (null? x))
       (not (pair? x))))

(define numbered?
  (lambda (aexp)
    (cond
      ((atom? aexp) (number? aexp))
      (else (and (numbered? (car aexp)) (numbered? (car (cdr (cdr aexp)))))))))

为什么可以简化

因为我们知道函数是正确的

(value u) 的值是多少,其中u是13

13

(value x) 的值是多少,其中x是(1 + 3)

4

(value y) 的值是多少,其中x是(1 + (3 ^ 4))

(value z) 的值是多少,其中z是cookie

没有答案

(value nexp) 返回我们认为的那样的数学算术表达式的值

期待如此

value 对nexp要几个查询

4个

现在,让我们试着写出函数 value

(define value
  (lambda (nexp)
    (cond
      ((atom? nexp) ...)
      ((eq? (car (cdr nexp)) (quote +)) ...)
      ((eq? (car (cdr nexp)) (quote ×)) ...)
      (else ...))))

由+把两个算术表达式相连而构成的算术表达式的值是多少

如果我们知道两个子表达式的值,我们把它们求和就可以了。

(1 + (3 × 4)中的里那哥哥子表达式的值是什么

当然是用value计算1,再用value计算(3 × 4)就可以了

总的来说呢

在子表达式上递归value

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
第七戒
在相同本性的东西上递归子组成部分:
*list表
*算术表达式
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

再试试函数value

(define value
  (lambda (nexp)
    (cond
      ((atom? nexp) nexp)
      ((eq? (car (cdr nexp)) (quote +)) (+ (value (car nexp)) (car (cdr (cdr nexp)))))
      ((eq? (car (cdr nexp)) (quote ×)) ('× (value (car nexp)) (car (cdr (cdr nexp)))))
      (else ('^ (value (car nexp)) (car (cdr (cdr nexp))))))))

你能想出算术表达式的不同表示吗

有好几种呢

(3 4 +)可以表示 3 + 4吗

可以啊

(+ 3 4) 可以吗

可以吗

或者(plus 3 4)

可以

(+ ( 3 6) (^ 8 2))是一个算术表达式的表达吗

是的。

试着谢谢函数value来处理一种新的算术表达式,可以是:
——是数
——是 + 后边跟着两个算术表达式
——是 × 后边跟着两个算术表达式
——是 ^ 后边跟着两个算术表达式

这个怎么样

(define value
  (lambda (nexp)
    (cond
      ((atom? nexp) nexp)
      ((eq? (car nexp) (quote +)) (+ (value (cdr nexp)) (car (cdr (cdr nexp)))))
      ((eq? (car nexp) (quote ×)) (× (value (cdr nexp)) (car (cdr (cdr nexp)))))
      (else (^ (value (cdr nexp)) (car (cdr (cdr nexp))))))))

你猜的没错

这个是错的

让我们试一试
(+ 1 3)

(atom ? nexp),其中 nexp 是(+ 1 3)

(eq? (car nexp) (quote +)) 其中 nexp 是 (+ 1 3)

现在递归

是的。

(cdr nexp) 是什么 其中 nexp 是 (+ 1 3)

(1 3)

(1 3) 现在i是我们算术表达式的表达了

不,我们违反了第七戒。(1 3)子部分不是一个算术表达式的表达。我们对一个list表做递归。但是不是所有的list都是算术表达式的表达。我们必须是对子表达式做递归。

怎样得到算术表达式的第一个子表达式

取cdr再去car。就是第二个list成员。

(cdr (cdr nexp)) 是一个算术表达式吗

不是,取cdr再取cdr就是(3)了,(3)不是算术表达式

再一次,我们之前把(+ 1 3)考虑的是表而不是算术表达式的表达。

取cdr取cdr再去car就得到了第二个子表达式,就是第三个list成员。

nexp取cdr再取nexp是什么

算术表达式的表达的第一个子表达式

我们来为算术表达式写一个函数1st-sub-exp

(define 1st-sub-exp
  (lambda (aexp)
    (cond
      (else (car (cdr aexp))))))

为什么else

因为第一个查询也是最后一个查询

我们可以把(cond ...)去掉吗,既然不需要分支查询

当然,第四章的rember一行版本的就是这样子的

(define 1st-sub-exp
  (lambda (aexp)
    (car (cdr aexp))))

为算术表达式写函数 2nd-sub-exp

(define 2nd-sub-exp
  (lambda (aexp)
    (car (cdr (cdr aexp)))))

最后我们把(car nexp)替换为(operator nexp)
(define  operator
  (lambda (aexp)
    (car aexp)))

现在再一次重写函数value

(define (atom? x)
  (and (not (null? x))
       (not (pair? x))))

(define operator
  (lambda (aexp)
    (car aexp)))

(define 1st-sub-exp
  (lambda (aexp)
    (car (cdr aexp))))

(define 2nd-sub-exp
  (lambda (aexp)
    (car (cdr (cdr aexp)))))

(define value
  (lambda (nexp)
    (cond
      ((atom? nexp) nexp)
      ((eq? (operator nexp) (quote +)) (+ (1st-sub-exp nexp) (2nd-sub-exp nexp)))
      ((eq? (operator nexp) (quote ×)) ('× (1st-sub-exp nexp) (2nd-sub-exp nexp)))
      (else ('^ (1st-sub-exp nexp) (2nd-sub-exp nexp))))))

我们可以对这一章的算术表达式的表达使用value函数吗

可以,通用改为使用 1st-sub-exp和 operator

试试看
(define 1st-sub-exp
  (lambda (aexp)
    (car (cdr aexp))))

(define operator
  (lambda (aexp)
    (car aexp)))

很简单不是吗

是的,因为我们用辅助函数来隐藏表达。

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
第八戒

使用辅助函数来抽象表达
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

我们之前见到过表达没

是的,只不过我们没告诉你

我们用过哪写表达

真值!数!

数是表达?

是的。比如说4是概念“4”。我们使用符号因为我们习惯阿拉伯数字表达。

我们还可以用什么表示呢

(() () () ())也可以表示。(((())))如何?(I V)怎么样?

还记得我们有多少个对数使用的元函数吗

四个:numbers? zero? add1和sub1

让我们再试试数的其它表示,零怎么表示

我们选择()

1 怎么表示
(())

2 怎么表示

(() ())

知道了?那3呢

(() () ())

写一个函数来测试是否是zero零

(define sero?
  (lambda (n)
    (null? n)))

写一个像add1函数的函数

(define edd1
  (lambda (n)
    (cons (quote ()) n)))

那sub1呢

(define zub1
  (lambda (n)
    (cdr n)))

这样对吗

让我们瞧瞧看

当n是()时(zub1 n)是多少

没有答案,但是没有关系。——回忆cdr的规则。

使用表达重写+

(define +
  (lambda (n m)
    (cond
      ((sero? m) n)
      (else (edd1 (+ n (zub1 m)))))))

+变了吗

Yes and no.它变化了,但是只是一点点。

回忆lat?

很简单:
(define lat?
  (lambda (l)
    (cond
      ((null?) #t)
      ((atom? (car l)) (lat? (cdr l)))
      (else #f))))
问这个干吗

还记得当ls是(1 2 3)时,(lat? ls)是什么吗

真,当然了。

对于我们的新数,(1 2 3)是什么

((()) (() ()) (() () ()))

那当ls是((()) (() ()) (() () ()))时,(lat? ls)是什么

这样有什么坏的地方吗

你必须得提防shadows了。


This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.5 China Mainland License.

the little schemer 笔记(6)的更多相关文章

  1. the little schemer 笔记(0)

    the little schemer 笔记 Z.X.L 2012年08月13日 五项规则 car的规则car只对非空列表有定义. cdr的规则cdr只对非空列表有定义.任何非空列表的cdr是另外一个列 ...

  2. the little schemer 笔记(10)

    第十章 What Is  the Value of All of This? entry条目 是由list表组成的 pair 对,pair 对的第一个list表是集合 set.另外,两个list表的长 ...

  3. the little schemer 笔记(3)

    第三章 cons the magnificent (rember a lat)是什么,其中a是mint,lat是(lamb chops and mint jelly) (lamb chops and ...

  4. the little schemer 笔记(10.1)

    This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.5 China Mainla ...

  5. the little schemer 笔记(9)

    第九章 ...and Again, and Again, and, Again, ... 你想来点鱼子酱吗? 那就去找它吧. (looking a lat)是什么,其中a是 caviar, lat是( ...

  6. the little schemer 笔记(8)

    第八章 lambda the ultimate 还记得我们第五章末的rember和insertL吗 我们用equal?替换了eq? 你能用你eq?或者equal?写一个函数rember-f吗 还不能, ...

  7. the little schemer 笔记(5)

    第五章 “Oh My Gawd”:It's Full of Stars (rember* a l)是什么,其中a是cup,l是((coffee) cup ((tea) cup) rember*发音为r ...

  8. the little schemer 笔记(7)

    第七章 Friends and Relations 这是一个set集合吗 (apple peaches apple plum) 不是,apple出现了不止一次 (set? lat) 是真还是假,其中l ...

  9. the little schemer 笔记(4)

    第四章 numbers games 14 是原子吗 是的,数都是原子 (atom? n) 是真还是假,其中n是14 真,14 是原子 -3是数吗 是的,不过我们暂不考虑负数 3.14159是数吗 是的 ...

随机推荐

  1. appium第一个安卓自动化工程

    转自:https://university.utest.com/how-to-set-up-your-first-android-automation-project-with-appium/ App ...

  2. 苹果应用内支付(iOS IAP)的流程与常用攻击方式

    1. 客户端直接verify苹果的receipt 如果verify成功 自行发放商品 2. 客户端将receipt传给server,由server进行验证并发放商品 按照安全性原则, 客户端的所有信息 ...

  3. 初始化master节点时,日志内容分析

    root@master:~/code/shell# kubeadm init --image-repository registry.aliyuncs.com/google_containers ++ ...

  4. redis中键值对中值的各种类型

    1 value的最基本的数据类型是String 2 如果value是一张图片 先对图片进行base64编码成一个字符串,然后再保存到redis中,用的时候进行base64解码即可. 这是base64的 ...

  5. redis12-----redis 与关系型数据库的对比

    书和书签系统 create table book ( bookid int, title ) )engine myisam charset utf8; insert into book values ...

  6. axios基于常见业务场景的二次封装

    axios axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中.在前端框架中的应用也是特别广泛,不管是vue还是react,都有很多项目用axios作为网络 ...

  7. java socket 以及 流 关闭的问题

    首先我一下几个提出问题:稍后再做出解答. 问题一:A如果仅仅将输入流关闭(inA.close()),对A与B之间的连接是否有影响? A能否再次获得输入流(inA = socketA.getInputS ...

  8. [Selenium] Selenium私房菜(新手入门教程)

    http://wenku.baidu.com/link?url=JrHF9o0mKWcpEsE-wijcZaneBWgpmAJPRwGyWXd7RvqzJCLLrsrsv5lf9bPRmgKUa_v- ...

  9. 「LuoguP3384」【模板】树链剖分

    题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式 ...

  10. [POI 2014] Little Bird

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=3831 [算法] 单调队列优化动态规划 时间复杂度 : O(N) [代码] #incl ...