the little schemer 笔记(6)
第六章 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)的更多相关文章
- the little schemer 笔记(0)
the little schemer 笔记 Z.X.L 2012年08月13日 五项规则 car的规则car只对非空列表有定义. cdr的规则cdr只对非空列表有定义.任何非空列表的cdr是另外一个列 ...
- the little schemer 笔记(10)
第十章 What Is the Value of All of This? entry条目 是由list表组成的 pair 对,pair 对的第一个list表是集合 set.另外,两个list表的长 ...
- the little schemer 笔记(3)
第三章 cons the magnificent (rember a lat)是什么,其中a是mint,lat是(lamb chops and mint jelly) (lamb chops and ...
- the little schemer 笔记(10.1)
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.5 China Mainla ...
- the little schemer 笔记(9)
第九章 ...and Again, and Again, and, Again, ... 你想来点鱼子酱吗? 那就去找它吧. (looking a lat)是什么,其中a是 caviar, lat是( ...
- the little schemer 笔记(8)
第八章 lambda the ultimate 还记得我们第五章末的rember和insertL吗 我们用equal?替换了eq? 你能用你eq?或者equal?写一个函数rember-f吗 还不能, ...
- the little schemer 笔记(5)
第五章 “Oh My Gawd”:It's Full of Stars (rember* a l)是什么,其中a是cup,l是((coffee) cup ((tea) cup) rember*发音为r ...
- the little schemer 笔记(7)
第七章 Friends and Relations 这是一个set集合吗 (apple peaches apple plum) 不是,apple出现了不止一次 (set? lat) 是真还是假,其中l ...
- the little schemer 笔记(4)
第四章 numbers games 14 是原子吗 是的,数都是原子 (atom? n) 是真还是假,其中n是14 真,14 是原子 -3是数吗 是的,不过我们暂不考虑负数 3.14159是数吗 是的 ...
随机推荐
- uboot1.1.6中启动流程
U-Boot启动内核的过程可以分为两个阶段,两个阶段的功能如下: (1)第一阶段的功能 Ø 硬件设备初始化 Ø 加载U-Boot第二阶段代码到RAM空间 Ø 设置好栈 Ø 跳转到第二阶段代码入口 (2 ...
- 基本SCTP套接字编程常用函数
sctp_bindx函数:允许SCTP套接字捆绑一个特定地址子集 #include <netinet/sctp.h> // 若成功返回0,出错返回-1 int sctp_bindx(int ...
- 我为什么不喜欢 CoreData
我为什么不喜欢 CoreData 我一直不喜欢 Core Data,以前不太敢明目张胆地这么表达,现在收集到越来越多相关的信息,所以给大家分享一下,我为什么不喜欢 Core Data. Core ...
- HDU 1022 Train Problem I (数据结构 —— 栈)
Problem Description As the new term comes, the Ignatius Train Station is very busy nowadays. A lot o ...
- Pycharm下运行程序查看每个变量的值的方法(类似于Spyder和MATLAB)
昨天,用了大量篇幅讲了Spyder的各种问题,之所以要用Spyder,最重要的一个原因就是能够非常方便的查看中间变量的值.类似MATLAB的工作空间,非常方便.如下图所示: 但是Spyder的代码自动 ...
- openwrt hotplug
由内核发出 event 事件. kobject_uevent() 产生 uevent 事件(lib/kobject_uevent.c 中), 产生的 uevent 先由 netlink_broadca ...
- openwrt 配置rsync服务
一: rsyn简介 remote synchronize顾名思意就知道它是一款实现远程同步功能的软件,它在同步文件的同时,可以保持原来文件的权限.时间.软硬链接等附加信息. rsync是用 “rsyn ...
- VC++ 学习笔记(四):停止还是暂停这个系列
我已经很久没有更新这个话题了,原因是多方面的,比如比较忙,比如我参与的项目不使用C++.最近因为需要在C#的客户端中调用第三方的C++API,又想起了这个话题.在跟公司里的C++方面专家聊过之后,我有 ...
- 编译异常之static和extern---more than one storage class specified
static 和 extern 不能同时共存 http://bbs.bccn.net/thread-58129-1-1.html
- node.js内存泄露问题记录
先说一下.事情的来龙去脉. 公司开发一款游戏棋牌游戏,服务端的开发是IO密集型,开发的时候,考虑过使用python,java,node.js. 终于选择了node.js(node.js宣传的杀手功能. ...