Lisp进阶
文章平均质量分 66
Lisp学习进阶
程序员需要学习的最后一门语言:Lisp
keyboardOTA
喜欢技术挑战
展开
-
SICP 习题 (2.23)解题总结:for-each的实现
SICP 习题 2.23 要求我们实现一个for-each过程。for-each过程和map过程其实很像,只不过for-each过程不返回值,如果返回一个值的话也是不包含意义的值。map比较像一个加工厂,进去一堆东西,加工一下,出来另一堆东西。for-each更像一个蒸汽机,进去一堆煤,燃烧一下,产生能量干点活,不出来东西,真的一定要说有东西出来也是煤渣,大家不在乎的东西。所以for-each更关原创 2015-01-16 00:31:35 · 2406 阅读 · 0 评论 -
SICP 习题 (2.22)解题总结: 迭代过程中的列表处理
SICP 习题 2.22是习题2.21的后续题目,题目中讲到叫Louis Reasoner的人想重写suqare-list过程,希望使用迭代计算过程,而不是递归计算过程,有关迭代计算过程和递归计算过程,如果你没什么印象了,请翻回习题1.9 的解题总结看看。那个叫Louis Reasoner的人写的迭代版的suqre-list是这样的:(define (square-list-revert item原创 2015-01-12 00:07:50 · 2980 阅读 · 0 评论 -
SICP 习题 (2.21)解题总结: map的使用
SICP 习题 2.21 开始引入了map,准确来讲,是这道题目前的文章内容开始引入了map。为了完成本习题,甚至说为了完成本文以后的阅读,请读者一定要理解清楚map的概念,正如书中所说,“map是一种很重要的结构,不仅因为它代表了一种公共模式,而且因为它建立起了一种处理表的高层抽象”。虽然说得非常高大上,但是map的概念理解起来并不困难,最基本的理解就是给你一组东西,你对这组东西执行map操作的原创 2015-01-10 20:44:01 · 2246 阅读 · 0 评论 -
SICP 习题 (2.20)解题总结: 不确定数量参数
SICP 习题 2.20 引入了一种新的函数调用方式,就是带 . 符号的不确定参数调用方式。题中也讲到了, Scheme支持这种调用方式,如果我们把方法定义成下面这个样子(define (my-method first-p . others-p) ;…..)我们就可以在调用方法my-method时传入大于2的任何数量的参数,比如:(my-method 1 2 3 4 5 6)这时my-原创 2015-01-08 23:30:42 · 2139 阅读 · 0 评论 -
SICP 习题 (2.19) 解题总结:重写零钱兑换程序
SICP 习题2.19 要求我们重新设计1.2.2节的零钱兑换程序,要求我们可以轻易改变程序里用的兑换币种。我们先看看1.2.2节的零钱兑换程序,代码是这样的:(define (RMB-Change amount) (format #t "Changing ~S~%" amount) (cond ((= amount 0) 0) ((< amount 0) 0) (else (RMB-原创 2015-01-07 00:14:14 · 2823 阅读 · 0 评论 -
SICP 习题 (2.18) 解题总结:反转列表
SICP 习题 2.18 要求我们定义一个过程名叫reverse,可以将一个list反转过来。比如 (reverse (list 1 4 9 16 25)) 的结果是:(25 16 9 4 1)这道题和之前的2.17有相似之处,都是对list进行遍历,然后做相应处理。不过2.17比较简单,遍历到最后面返回最后的元素就好了,2.18复杂一点,需要在遍历之后将list元素反向组装起来。我们可以按以前的原创 2014-12-25 00:13:10 · 3324 阅读 · 1 评论 -
SICP 习题 (2.17)解题总结:列表的遍历
SICP 习题 2.17 要求我们定义出过程last-pair,它返回只包含给定表里之后一个元素的表。比如 (last-pair (list 23 72 149 34))的结果应该是(34)当你开始做这道题的时候你应该已经看完书中有关list操作的内容了,你应该明白car和cdr分别是什么意思,也应该知道如何通过递归调用遍历一个list。有了以上基础的话完成习题2.17就是小菜一碟啦,基本思路就是原创 2014-12-25 00:12:01 · 2380 阅读 · 2 评论 -
SICP 习题 (2.16)解题总结:避免误差的区间计算系统
SICP 习题 2.16 问我们能不能设计一个没有问题的区间计算系统,可以避免习题2.14中的问题。题目还吓我们说这可能很难。这一下就把我吓住了,你不是说很难吗,那就很难吧,我不会。呵呵原创 2014-12-24 22:05:54 · 2767 阅读 · 2 评论 -
SICP 习题 (2.15)解题总结:区间误差的深入思考
SICP 习题 2.15 是接着 题目 2.14 的, 题目 2.14中提到了Alyssa设计的区间计算模块在并联电阻计算时会出现问题,这个问题是Lem发现的。接着,一个叫Eva的人也发现了这个问题,同时她还有更深入的思考。Eva觉得,如果一个公式可以写成一种形式,其中具有非准确性的变量不重复出现,那么Alyssa的系统产生的区间的限界会更紧一些。因此,她觉得在计算并联电阻时,公式“1/(1/R1原创 2014-12-23 22:23:36 · 2391 阅读 · 0 评论 -
SICP 习题 (2.14)解题总结:区间误差导致的问题
SICP 习题 2.14 的题目要求并没有完全体现在题干中,这道题是和书中前面的内容相关的。书中讲到,Alyssa做完了我们以前讨论的区间计算模块并发布出去了,然而,一段时间以后她接受到了来自一个叫做Lem的工程师的抱怨,这个叫做Lem的人应该是搞电路的,他用Alyssa的程序去计算两个电阻的并联电阻值,里面就使用了Alyssa设计的区间来表示一个电阻的电阻值。按照物理上的定律,并联电阻的公式是(原创 2014-12-16 16:33:43 · 11563 阅读 · 0 评论 -
SICP 习题 (2.13)解题总结:区间计算误差
SICP 习题 2.13 又像是一道数学证明题,和编程关系不大,不过这不能阻挡我们去完成它。题目要求我们证明,当误差百分比很小的时候,可以使用一个简单的公式,根据被乘区间的误差去计算乘积的误差。同时,为了简化问题,题目允许我们只计算所有数为正的情况,因为涉及到负数时,乘积的正负变化比较多样,不容易统一处理。我看到题目后最直接的反应不是去证明它,而是通过程序去找到这个简单的公式,典型的程序员心理。要原创 2014-11-23 15:39:42 · 33682 阅读 · 1 评论 -
SICP 习题 (2.12)解题总结 :区间的不同实现方式
SICP 习题 2.12 要求我们定义一个构造函数make-center-percent,它接收两个参数,分别代表中心点和一个误差百分比。我们需要通过这个构造函数产生一个区间。此外还需要定义一个选择函数percent,用来获取指定区间的误差百分比。还有就是需要实现一个center函数用于获取区间的中间点。这里的关键就是要我们明白一个复合数据类型可能会有不同的表现形式,比如这里的区间可以用起点和终点原创 2014-11-13 01:09:59 · 63173 阅读 · 5 评论 -
SICP 习题 (2.11)解题总结:区间乘法的优化
SICP 习题 2.11又出现Ben这个人了,如以前说到的,只要是Ben说的一般都是对的。来看看Ben说什么,他说:“通过监测区间的端点,有可能将mul-interval分解为9中情况,每种情况中所需要的乘法都不超过两次”。所以这个叫Ben的人建议Allysa重写mul-interval过程。到底是啥意思呢,我们先来看看以前的mul-interval过程:(define (mul-interval原创 2014-10-29 00:31:35 · 56220 阅读 · 1 评论 -
SICP 习题 (2.10)解题总结: 区间除法中除于零的问题
SICP 习题 2.10 要求我们处理区间除法运算中除于零的问题。题中讲到一个专业程序员Ben Bitdiddle看了Alyssa的工作后提出了除于零的问题,大家留意一下这个叫Ben的人,后面会不断出现这个人,只要是这个人提到的事情一般是对的,他的角色定位是个计算机牛人。对于区间运算的除于零的问题,处理起来也比较简单,只需要判断除数是不是为零,除数为零就报错。对于一个区间来讲,所谓为零就是这个区间原创 2014-10-11 00:17:50 · 48017 阅读 · 0 评论 -
SICP 习题 (2.9)解题总结:区间的宽度和区间加减乘除的关系
SICP 习题 2.9 像是一个数学题,要我们证明区间的和与差的宽度是被加和被减的区间的宽度的函数,而对于乘法和除法来说不成立。书中所谓宽度就是区间起点和终点差的一半,以我看来更像是区间宽度的一半,不管怎么样,差不多是一个意思。如果你把区间看成是一个线段的话,所谓宽度应该就是起点和终点的差,如果一定要把宽度的一半记作是宽度也无所谓的。证明区间的和的宽度是被加区间的宽度的函数这一点是比较容易证明的,原创 2014-10-10 00:24:02 · 29370 阅读 · 0 评论 -
SICP 习题 (2.8) 解题总结:区间的减法
SICP 习题 2.8 需要我们完成区间运算的减法,区间运算的加法书中已经有了,代码如下:(define (add-interval x y) (make-interval (+ (lower-bound x) (lower-bound y)) (+ (upper-bound x) (upper-bound y))))以上代码很简单,就是计算区间的加法时将两个区间的起点相加,称为新区间原创 2014-10-09 00:09:04 · 8291 阅读 · 3 评论 -
SICP 习题 (2.7) 解题总结 : 定义区间数据结构
SICP 习题 2.7 开始属于扩展练习,可以考虑不做,对后面的学习没什么影响。不过,如果上面的使用过程表示序对,还有丘奇计数你都可以理解的话,完成这些扩展练习其实没什么问题。习题2.7是要求我们协助Allysa完成interval的定义。Allysa定义了下面的过程来创建一个区间(interval),其中a是起点(就是较小的部分),而b是终点(就是较大部分)。(define (make-inte原创 2014-10-08 00:46:22 · 6399 阅读 · 0 评论 -
SICP 习题 (2.6) 解题总结:丘奇计数
SICP 习题 2.6 讲的是丘奇计数,是习题2.4 和 2.5的延续。 这里大师们想提醒我们思考的是“数”到底是什么,在计算机系统里可以如何实现“数”,准备好开始脑洞大开吧:题目先讲到下面的定义,首先是0的定义:(define zero (lambda (f) (lambda (x) x)))然后是操作+ 1的定义:(define (add-1 n) (lambda (f) (lambda原创 2014-09-29 00:33:09 · 5956 阅读 · 1 评论 -
SICP 习题 (2.5) 解题总结:复合数据的指数表示
SICP 习题 2.5 有点像是道数学题,首先要求我们证明可以将a和b的序对表示为2^a * 3^b,然后通过非负整数和算术运算表示序对。最后要求我们实现对应的cons, car 和cdr过程。这道题的根本就是复合数据的构成方式和解析方式。其实,对于所有复合数据来讲,我们都在处理同样一件事情,就是如何把复合数据的组成部分构建在一起,同时可以通过特定的方法将它们拆解出来。就好像我们要存放乒乓球和网球原创 2014-09-28 00:40:25 · 4684 阅读 · 0 评论 -
SICP 习题 (2.4) 解题总结:序对的过程性表示
SICP 习题 2.4 是一道很有意思的题目,它在一定程度上会改变你对数据结构的认识。按题目的说法,这里讲到的是“序对的过程性表示”。序对大家应该熟悉了,前面几道题都和序对有关系,那序对的“过程性表示”是什么意思呢?简单一点说就是用一种过程(或者说函数啦)来实现序对。在此之前,对于很多程序员来讲,数据是数据,过程是过程,两者是单独存在的,过程一般是用来访问数据的。像这里讲到的使用一个过程来实现数据原创 2014-09-26 00:59:36 · 3967 阅读 · 0 评论 -
SICP 习题 (2.3) 解题总结:用复合数据表示矩形
SICP 习题 2.3 要求我们实现一种平面矩形的表示,定义获取数据的相关选择函数。然后定义几个过程来计算矩形的周长和面积。接着题目还要求我们实现矩形的另一种表示方式,要求这个新的矩形表示方式同样适用于以上定义的周长和面积计算过程。有关这道题我们可以通过由上而下的方式进行实现,实现过程也不算复杂,原因是这道题涉及到的数学概念还是比较简单,就是矩形的面积和周长,差不多是我们小学的知识吧。不过题目后面原创 2014-09-24 00:16:46 · 3916 阅读 · 0 评论 -
SICP 习题 (2.2) 解题总结:用复合数据表示点和线段
SICP 习题 2.2要求我们使用这一节的数据抽象方法定义几何里“点”的概念,还要定义“线段”的概念,最后还要求我们定义midpoint-segment过程,这个过程根据参数中的线段进行计算,返回该线段的中点。题目还给出了一个print-point过程,用于输出一个点,代码如下:(define (print-piont p) (newline) (display "(") (displ原创 2014-09-23 00:10:16 · 3955 阅读 · 0 评论 -
SICP 习题 (2.1) 解题总结:用复合数据表示有理数
SICP 习题 2.1 要求我们做一个可以正确处理正数和负数的make-rat过程,用于生成一个有理数。条件是分母必须是正数。完成这道题本身比较简单,就是简单修改一下书中的make-rat过程就可以了。书中原本的make-rat过程如下:(define (make-rat n d) (cons n d))可以发现,原来的make-rat就是简单地将n和d组成一个序对,然后返回这个序对,并没有对原创 2014-09-22 00:16:40 · 4730 阅读 · 0 评论 -
SICP 习题 (1.46)解题总结:第一章的收官题
SICP 习题 1.46 要求我们写一个过程iterative-improve,它以两个过程为参数,其中一个参数用来检测猜测是否足够好,另一个参数用来改进猜测。过程iterative-improve应该返回另一个过程,所返回的过程接收一个参数作为初始猜测,然后不断改进猜测直到结果足够好。题目还要求我们使用iterative-improve重写1.1.7的sqrt过程和1.3.3节的fixed-po原创 2014-09-20 22:41:37 · 4213 阅读 · 1 评论 -
SICP 习题 (1.45)解题总结
SICP 习题 1.45是对前面很多关于不动点的习题的总结。题目回顾了我们之前在1.3.3节使用的不动点寻找方法,当寻找y -> x/y 的不动点的时候,这个变换本身不收敛,需要做一次平均阻尼才可以。对于y -> x/(y^2)这个变换也可以通过一次平均阻尼使它变得收敛。不过一次平均阻尼对于四次方程是不够的,就是说,对y -> x/(y^3)这样的变换,一次平均阻尼不足以使它收敛,需要做两次平均阻原创 2014-09-18 23:32:15 · 2748 阅读 · 0 评论 -
SICP 习题 (1.44)解题总结
SICP 习题1.44 要求我们实现一个平滑函数的过程,和以往一样,如果你太在意平滑函数的数学定义你就输了。简单的办法就是直奔平滑函数的要求,其实就是给我们一个不清楚细节的函数f,要求我们返回一个过程专门计算(f (+ x dx)) , (f x) , (f (- x dx))的平均值。其中dx是事先定义好的一个很小的数,比如0.001。这就比较简单了,直接实现如下:(define (smooth原创 2014-08-24 18:28:38 · 2061 阅读 · 0 评论 -
SICP 习题 (1.43)解题总结
SICP 习题 1.43 是前面两道题的延续,习题要求我们定义一个过程(repeat f n) ,其中f是一个单参数过程,题目要求我们通过repeat过程将过程f调用n次,注意是嵌套调用n次,不是连续调用n次。就是说结果应该是(f ( f ( … (f x) …))),而不是(begin (f x) (f x) (f x) … (f x))。题目还提醒我们使用习题1.42所定义的compose方法原创 2014-07-01 00:12:44 · 4185 阅读 · 1 评论 -
SICP 习题 (1.42)解题总结
SICP 习题 1.42 出人意料的简单,题目要求我们定义一个名为compose的过程,该过程接收两个参数,都是单参数过程,要求我们将这两个参数代表的过程串起来。题目举例((compose square inc) 6)等于49,其中inc过程接收一个参数,执行加一操作,而square过程也只接收一个参数,执行求平方操作,6加1再求平方就是49了。如果习题1.41都做完了,这道题就比较简单了,定义原创 2014-07-01 00:11:55 · 4030 阅读 · 0 评论 -
SICP 习题 (1.41)解题总结
SICP 习题1.41 看似和周边的题目没有关系,突然叫我们去定义一个叫double的过程,其实这道题的核心还是高阶函数。题目要求我们定义一个过程double,它以一个过程作为参数,这个作为参数的过程已经约定是一个单参数过程。double过程需要返回一个过程,所返回的过程将传入的过程应用两次。举例说,如果我们有个过程叫(扇耳光 贱人),调用这个过程会扇贱人一个耳光。那么(double 扇耳光)会返原创 2014-06-26 00:14:51 · 7023 阅读 · 0 评论 -
SICP 习题 (1.40)解题总结
SICP 习题1.40 是一道题干很简单,但是看起来很复杂,本质其实比较简单的一道题。题目原题如下:请定义一个过程cubic, 它和newtons-method过程一起使用在下面形式的表达式里:(newtons-method (cubic a b c) 1)能逼进三次方程的零点。题干是很简单,就要求我们做个cubic过程,不过里面涉及newtons-method和三次方程的零点,如果只看题目的话真原创 2014-06-26 00:11:03 · 6871 阅读 · 0 评论 -
SICP 习题 (1.39)解题总结
SICP 习题1.39沿着习题1.37, 1.38的方向继续前行,要求我们根据德国数学家J.H.Lambert的公式定义tan-cf过程,用于计算正切函数的近似值。J.H.Lambert的公式如下:可以发现,这个和之前的无穷连分式是一样一样的,所不同的就是N是一个变量,不是固定数值。不过这个已经难不倒我们啦,可以从公式中发现,除了第一个N是x,其它的N都是x平方,D对应的数值是1,3,5,就是所有原创 2014-06-18 00:43:12 · 7148 阅读 · 2 评论 -
SICP 习题 (1.38)解题总结
SICP 习题1.38 紧跟着习题1.37的方向,要求我们用习题1.37中定义的cont-frac过程计算数学家欧拉大师在论文De Fractionibus Continuis 中提到的e-2的连分式。说实话,我不知道论文De Franctionibus Continuis讲的是什么,我甚至不知道论文的题目是什么意思。不过,这一切都不能阻止我这个数学盲去解答这道SICP习题。仔细阅读题目,我们可以原创 2014-06-18 00:42:08 · 7080 阅读 · 0 评论 -
SICP 习题 (1.37)解题总结
SICP 习题 1.37是一条很长的题目,主要讲的是无穷连分式。无穷连分式对我来说又是一个陌生的概念,于是又去百度了一番,发现无穷连分式也是一个很有意思的话题,涉及到无理数的表达。不过我建议大家还是暂时不要深入思考它的数学含义,一旦开始思考可能你又会跳进数学的深渊中不可自拔。无穷连分式的形式如下:就像书中说到的,作为无穷连分式的一个特殊例子,如果N和D都为1的话,f= 1/ φ, 这点可以结合我们原创 2014-05-29 23:56:38 · 4559 阅读 · 1 评论 -
SICP 习题 (1.36)解题总结
SICP 习题 1.36 要求我们修改fixed-point函数,使它能够打印出计算中产生的近似值序列,使用练习1.22展示的newline和display方法。而后通过找出变换x => log (1000)/log(x)的不动点的方式确定x^x=1000的一个根(书中还提示你使用Scheme的基本过程log,用于计算自然对数值)。然后比较一下使用平均阻尼和不用平均阻尼的计算步数。要注意的是不能使原创 2014-05-02 19:53:41 · 3933 阅读 · 0 评论 -
SICP 习题 (1.35)解题总结
SICP 习题 1.35要求我们证明黄金分割率φ 是变换函数 x => 1+ 1/x 的不动点,然后利用这一事实通过过程fixed-point 计算出φ的值。首先是有关函数的不动点,这个概念需要理解清楚,后面好几道题都是围绕函数不动点展开的。作者在这里设计这些习题的原因也是希望读者可以关注函数不动点。其实有关不动点这个东西我在做习题“1.8”的时候就觉得好奇了。为什么“(x+x/y)/2”会不断逼原创 2014-04-29 00:10:35 · 3905 阅读 · 0 评论 -
SICP 习题 (1.34)解题总结
SICP 习题 1.34的题目比较特别一点,对于没有接触过高阶函数的同学们来说是个很好的学习机会。题目是这样的,如果我们定义下面的过程:(define (f g) (g 2))那么就有:(f square) => 4因为有(f square) => (square 2) => 4还有(f (lambda (z) (* z (+ z 1)))) => 6因为有(f (lambda (z) (* z原创 2014-04-20 20:20:06 · 3689 阅读 · 0 评论 -
SICP 习题 (1.33)解题总结
SICP 习题 1.33将之前抽象的accumulate过程继续往上拔,要求我们定义一个带过滤器的accumulate过程,在这个过程中加多一个参数,这个参数是另一个过程,用来做过滤器。比如我们调用(filtered-accumulate 奇数?+ 0 my-self 1 next-int 100)就是列出1到100的数,对每个数调用(奇数? n),如果结果为真就将这个数加入到累积结果中,如果结果原创 2014-04-13 01:15:23 · 4320 阅读 · 0 评论 -
SICP 习题 (1.32)解题总结
SICP 习题1.32要求我们考察之前完成的sum过程和product 过程,说明它们是名为accumulate的过程的特殊情况。反过来说的话,就是要我们对sum过程和product过程进行抽象,形成一个更普遍,更通用的过程。我们在习题1.31的解题总结中已经讨论了,其实sum过程和product过程相差很小,就是累积的操作不一样,初始化的数值不一样。这样,我们就可以将不同的东西抽离出来,定义一原创 2014-04-08 00:09:40 · 4463 阅读 · 0 评论 -
SICP 习题 (1.31)解题总结
SICP 习题1.31开始拔高我们的抽象能力,向更高的高度进发,以更好地理解高阶函数。习题1.31是基于1.30的。在习题1.30中我们定义了累加的过程sum,其实我们可以发现,这种累积操作是可以做更高的抽象的。在做更高的抽象之前让我们看看使用乘法做累积的代码是什么样的,这就是题目要求我们完成的第一个任务,做函数值的乘积。定义出来的过程如下:(define (product term a next原创 2014-03-31 00:25:54 · 3187 阅读 · 0 评论 -
SICP 习题 (1.30)解题总结
SICP 习题1.30看上去像是一条复习题,要求我们将一个线性递归过程改写成一个迭代过程。需要改写的过程如下:(define (sum term a next b) (if (> a b) 0 (+ (term a) (sum term (next a) next b))))不过仔细看看题目就会发现,这道题和一般的递归该迭代的习题不同,这道题把过程term 和nex原创 2014-03-16 00:59:57 · 3440 阅读 · 0 评论