全部学习汇总: GitHub - GreyZhang/g_SICP: learn SICP and hack lisp.
这是对前面计算树的叶节点的代码结构的一个重用,理解起来还是很简单的:到了叶子的时候,进行一个奇偶判断,既然根据判断结果求平方。如果满足条件,返回平方,不满足则是0。通过一个递归的处理,进行所有节点的处理求和。
这个函数实现了构建前n个斐波那契数列的偶数构成的list。但是没有理解到原文想要表达的意图,这两个实现处理的对象完全不同,一个是一个树,另外一个是一个函数。当然,函数的数据有树的特征。这里需要找出来的是一个什么共性呢?
这里为了提取出来共性,列述了两个过程的处理信息。
其实整个设计的过程中都有一个过滤的过程,但是很遗憾的是这个过滤的过程其实是没有什么函数化抽象支持的。
如果处理的内容列表化之后,就可以使用一些通用的技巧,比如map操作修改数据。如果想要按照某一个条件来进行数据筛选,上面的这段还是是可以实现的。函数也是一个递归的过程,如果判断一个car的元素是满足条件的,那么就组合到一个列表当中。组合的方式是在列表的前面增加筛选出来的元素以及剩下的所有元素。感觉这样产生的过程其实是很耗费资源的,其实是有点堆栈处理的感觉。得递归的处理序列进入到解析器的上下文环境之后,从后面向前进行求解。
这里测试了上面的过滤器的设计,同时又给出来一个对全部的元素进行综合处理的方式。做了几个测试,这个综合处理的方式其实是一个遍历组合的过程,组合的结果最终取决于传入的处理方式。而这个处理,似乎应该是跟前面的过滤器很好的组合元素。另外,再增加一个map,可以实现处理覆盖度较高的需求。
这是一个枚举序列生成的过程,这个过程使用的又是一个递归的实现。
引入了一个前面设计的filte的操作,可以根据传入的第一个函数进行对后面元素的测试。测试成功之后,这个元素才是有效的,否则的话跳过。这里,又利用了前面构建出来的两个函数。这里有一段标注了颜色,提到了列表话对于模块化设计的一个有效性。后面的补充也增加了一定的说明,其实这个复用给我的感觉略微牵强了一些。但是这种序列化,然后统一进行常规处理的思路在嵌入式C开发中其实也是可以得到很好的借鉴使用的。
如此,求解所有奇数数字的平方和。可以是先把列表中的奇数筛选出来,用到filter,然后进行每一个元素的平方化修改,用到map,之后来一个累积的加法操作。同样,一范围内偶数斐波那契数列的元素筛选也是类似的处理方式。
针对前面提到的问题,这里给出了代码以及运行结果。代码的构建分析很简单,首先确认这个过程是一个累积的过程。但是累积出来的结果是一个list,因此累积的方法是cons。求取前面n+1的斐波那契序列,首先得生成相应的index值,这就用到了前面的枚举过程。为每一个对应的index生成斐波那契数,map一下fib函数到index序列。如果再求解每一个数值的平方生成新的序列,继续map一个平方求解函数到fib序列。之后,进行累积过程即可。
找出一个序列中所有的奇数,然后计算平方,之后求乘积。解读的过程也很简单了:过滤出来奇数,然后map一个求平方,之后累积乘法。
推而广之,假定条件下从一个记录中找出工资最高的程序员的薪水的处理也很容易理解了。
这是一个实现方式。突破点其实很简单,map结果其实是一个list,因此lambda实现的功能一定具有cons的行为。接下来,考虑如何做一个函数调用组合即可。
关于第二个append的实现,我多少费了一点脑筋理解。
这是一个实现以及测试,为了能够表征具体的设计生效了,我直接换了一个名字然后查看了解析器中信息。我费脑筋的地方在哪里呢?其实还是在于递归的理解。递归,其实是层层推理,从前往后逐步分析整个过程,然后再从后往前进行倒序的逐步求解。这个理解是没有问题的,但是有问题的地方在于这个过程并不意味着所有的求解出来的顺序都是反着的。accumulate递归实现,其实在从前往后推理分析的时候已经形成了列表数据,只是这个列表数据待求解。通过递归的处理,从后往前计算出来结果,但是其实整个数据顺序在列表中是没有变化的。
对于length的实现很简单,跟前面的分析其实方法类似。这里需要的是一个lambda表达,而其最终的行为表现一定是+。每一个元素的长度其实是明确的,就是1,这样很容易设计出这个实现。
这个问题的确是有点让我费脑筋,我对数学类的很多东西都不是很敏感。但是这个表达式在处理的时候,凭借C的经验很容易想到一个循环迭代来实现。如果从前面的计算模式,首先也得确认出来这个表达式最终实现的其实是一个加法运算。那么,如果实现最后的求解呢?先把加法的架构写上,根据进一步的表达式构建出来如下程序。
其实,类比一个C语言的for循环比较好理解这个问题。结果计算的是否正确呢?直接用python做一个检查。
通过计算,看出来结果是正确的。开始的时候,理解这个问题的时候进了一个误区。一个很大的问题点在于:不要把x当做未知数,否则会带来一定的费解。
这个章节花费的时间有一些多了,也小有收获。相应的学习甚至中间还出现了回炉才让我慢慢理解了这个设计的过程。后面的练习题暂且不做了,先继续走到下一个小章节标题中去。