对SCHEME的一些理解(2)
平时抽空看看SICP,主要是为了理解一些UNIX设计问题,另外也能揣摩最早一批计算机黑客的技术发展历程,UNIX将一切都是文件,一切最好都用文本的思想全面贯彻到系统设计中,想要领悟其哲学,必定得掌握最接近机器模型的C语言和最强文本处理能力的LISP,再说,一代UNIX黑客几乎都是LISP黑客(主要是MIT人工智能实验室中的那群人),UNIX也是其最主要的两位作者将经验主义和理论主义完美结合的典范,个人觉得Ken Thompson设计的UTF-8编码就有浓重的经验主义意味,也透露出一些无厘头的搞怪气氛,可能是又一次对KISS原则的贯彻吧。《UNIX编程艺术》和《黑客和画家》这两本具有浓厚技术黑客文化意味的书籍都有指出,程序员不是科学家,更像创作者,用现有的技术发明的新的创意,所以很有可能对于程序员来说,经验甚至比科学理论基础更重要。
言归正传,我在做SICP习题时,会拿一些我觉得比较有启发意义的题目做深入点的分析,给自己留个笔记(如上篇对习题2.6的分析)。现在来看习题2.18(我看书比较慢),这道题不算很难,但我觉得它着重点出了前递归和后递归的差别(没专门学过算法,不知道怎么描述),要打印题目要求的样式,list必须是前数据后pair模式,就是(car list)返回数据,(cdr list)返回还是个list,我看了下SICP之前都是用的前递归模式,所以我第一次写了这样一个习惯性的答案:
(define clist
(cons 21
(cons 22
(cons 23
(cons 24
(cons 25 ()
))))))
(define (reverse x)
(if (null? (cdr x))
(car x)
(cons (reverse (cdr x))
(car x))))
打印结果为:
((((25 . 24) . 23) . 22) . 21)
数字是倒过来了,可惜用的数据结构不对,这个打印结果表示成scheme语法如下:
(cons (cons (cons (cons 25 24) 23) 22) 21)
和想要的模式正好相反,(car list)返回的是list,而(cdr list)返回的是数字。造成这个结果的主要原因是reverse是前递归式的,也就是说递归展开后cons的操作是从前向后顺序计算的,我们需要将list的所有数据car出来,然后从后向前进行cons操作,也就是说cons操作要先于递归展开,有一种方法可以做到这点,就是将cons包含reverse的模式,改为reverse包含cons,将cons结果作为参数传递给reverse,这样就能在递归展开前进行cons操作了,修改后的reverse如下:
(define (reverse-1 x part)
(if (null? (cdr x))
part
(reverse-1 (cdr x)
(cons (car x) part)
)))
写的好看点:
(define (reverse k)
(define null ())
(define (reverse-1 x part)
(if (null? (cdr x))
part
(reverse-1 (cdr x)
(cons (car x) part)
)))
(reverse-1 k null))
总结一下,如果要在递归完成的同时就完全所有操作,就将要的进行的操作和判断条件通过参数传入函数,如果要在递归收敛时进行相关操作,就将递归函数作为参数传递给操作。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库