全部学习汇总: GitHub - GreyZhang/g_SICP: learn SICP and hack lisp.
这段信息读下来,开始有一点模糊。其实到了最后这一部分代码,理解突然间感觉容易了,也一下子似乎知道了这个思维模式应该怎么类比处理了。其实,这一段的代码处理,在实现方式上很像C语言中接触到的冒泡排序。而map以及accumulate等函数,实现的功能本质还是遍历处理。
基于上面的理解,把这段代码做一个详细的理解。首先,这个是一个对accumulate的调用,实现的最终当然是一个append的作用的组合。初始值为nil,组合的对象是后面的一个列表。这个列表是通过map进行处理的,处理的行为其实有一个map映射,把一个1到i-1的列表处理成与i组合到一起的列表。这样,只要给一个i,其实就可以生成i与i-1的所有组合。而后面有一个枚举,给出了所有的i的选择为1到n。
把这个过程做一个抽象,后面完成的功能就是利用proc更新seq的每一个元素,然后在把每一个元素组合在一起。这里需要注意的是,proc处理的是一个列表,而seq其实是由子列表组成。接下来,针对这个做一个测试加深理解。
(define (flatmap proc seq)
(accumulate append nil (map proc seq)))
(define (my-sq x) (* x x))
(define (my-sq-list x) (map my-sq x))
设计上面的一个接口my-sq-list,功能很简单,把一个列表的元素全都更新为平方。
基于这个函数,做上面的测试,这样上面的函数设计的意图也就十分明确了。
这一段设计是很好理解的了,判断一个pair的两个元素之和是否是素数。
这个函数的功能就是生成前面列表中的一组数据,两个数字一个和。
综合前面的描述,就可以设计出来上面的实现。这一段代码实现理解花了一点时间,我觉得最让我不解的还是flatmap本身的功能。但是,当这个能够以一个例子的方式实现后,前后的障碍也就全都通了。
嵌套映射不仅仅适用于枚举类的列表,这里以一个排列组合的例子来做说明。生成排列组合的方式可以用递归实现,确定一个,递归剩余。这个跟钱币的处理还是很类似的,很容易理解。
remove的实现很巧妙,一个filter就结束了。
这个章节熬的时间太久了,偷个懒,跳过后面的练习题了。