对SCHEME的一些理解(1)

📅 2026/7/5 4:48:42
对SCHEME的一些理解(1)
最近抽空阅读SICP并重温《黑客帝国》这个电影给了我在计算机程序设计上有了一些灵感的启发在正式谈论SICP之前我想先对scheme及其在程序设计语言中的地位作个简单解释LISP是一门非常古老的语言据说仅FORTRAN比其老迈在经历多年落寞之后LISP突然焕发光彩新近的流行语言不断从中吸取养分茁壮成长比如C#加入LAMBDA表达式JS的闭包垃圾回收等为什么LISP在分支方言众多而且没有组织统一维护的不利状况下能如此潇洒得意。现在将自己的一些理解写下笔记方便后面温习查询。我喜欢scheme因为他小且纯粹我不指望能直接用LISP做一些现实开发只希望靠它开启我的思维很多人之所以觉得LISP入门极难或者SICP这本书起点太高只是因为我们基础太差相信如果我们之前有离散数学、数理逻辑的基础看起来必定轻车熟路因为相比计算机编程语言LISP更像数学它比C/C更为基础和原始就如donald e.knuth所言计算机科学只不过是数学的一层漂亮外衣没有离散数学、组合数学、概率论、抽象代数、基础微积分等基础数学知识而直接阅读《计算机程序设计艺术》不但异常艰难而且收效甚微所以在看这套计算机科学经典之前最好先看看作者的另一本书《具体数学》这是题外话现在我证明给你看为什么lisp比C更为原始夸张一点说更接近真理本质。打个不太恰当的比喻吧你觉得1米/秒和1千克哪个大你觉得数字1和运算符有什么关系你可能会说你不是白痴吧两个完全不同的东西你怎能拿来类比我想说的是不要和matrix的奴隶一样要学neo尽可能看透这个世界很多人都相信真理是简单的我也相信。几百年前没有人会觉得我们和植物有什么相同而现在我们知道了其实我们很像都是由DNA/RNA传递遗传信息都由细胞构成几十年前没有人觉得我们和水有什么相同现在我们知道了其实我们都是由有限的几种元素组成。爱因斯坦发明了质能方程统一能量和质量质量和能量其实可能只是一种事物的不同表现不要被一切美丽的外表所迷惑借用《黑客帝国》中的台词何为真实你所看到的你所嗅到的这些只不过是你大脑的反应。而现在的一切知识模型很可能在未来都会慢慢推翻直到找到真理。这里有一个可观察和可测量的概念就如牛顿的万有引力牛顿不知道万有引力到底是什么他只是找到了它的作用规律在没有找到真理之前所有知识都只是事物的近似抽象模型很多我们习以为常的概念却不是那么显而易见比如数字‘0’到底是什么如何严格定义你别告诉我一个圈就是个零我也不清楚但我知道这个问题不是那么显而易见比如如果一个“东西”它和任何其他东西的积是它本身它就是零那么只要一个东西满足这个约束条件那他就是“0”正好说明SICP第二章关于序对的阐释不管底下如何组织序对我只需要一个可以生成序对、两个取出前后元素的方法就行SICP展示为了完全用过程表示数据的方式让人大吃一惊我们关心的是可以真正触摸产生效果的接口一切无法观察的东西对我们来说都是没有意义的见“看不见的龙”小故事这个世界充满着一个规律世界上所有物体都是透过其可以对外界产生作用的接口让外在得以察觉认识我们知道的只是这些接口而内部的真理却无法窥见。可以言归正传了看看SICP习题2.6整个SCHEME建立在唯一一条规则上lambda演算。发明者是著名数理逻辑学家alonzo church已经证明了lambda演算是图灵完全的所以一定程度上讲基于lambda演算的scheme和基于机器模型的C语言计算能力是完全等同的。C语言中数据和操作是严格区分的静态的数据和动态的操作在我们脑海中已经根根深蒂固但根据以上的论述我可以想到只要能发明一个东西能完全满足数字的定义那这个东西就可以完全代替数字了本质上就是lambda演算还真有这个能力用操作实现数据。以下一些概念可能牵涉到数学中的实分析推荐一本书《陶哲轩实分析》大家可以看看如何用基本规则构成复杂的数学大厦如果没有实分析理论基础看数据抽象这块会有一些障碍。SICP中的例子非常简单要大家用lambda演算建立整数自然数体系及自然数加法规则。它先定义了数字0(define zero (lambda (f) (lambda (x) x)))然后定义了自增1操作(define (add-1 n)(lambda (f) (lambda (x) (f ((n f) x)))))很显然有了这两个规则其他自然数都可以定义出来了1 (add-1 zero)2 (add-1 (add-1 zero))3 (add-1 (add-1 (add-1 zero)))...这样表示不够直接换成如下(define one (lambda (f) (lambda (x) (f x))))(define two (lambda (f) (lambda (x) (f (f x)))))(define three (lambda (f) (lambda (x) (f (f (f x))))))大家看见了吧任何自然数被都定义成过程我们再在这些过程上定义等同的四则运算然后提供转换到阿拉伯自然数空间的方法就建立了属于自己的自然数体系了。这里SICP让我们定义一个基于lambda自然数定义的原生加法很简单a b的加法效果只需要等同于0自增a加b次就算成功了为了更简单的检查结果到底准确与否先实现一个lambda自然数体系到阿拉伯自然数体系的简单方法(define (print-x n)(define (mark x)(display 0))((n mark) 0))使用方法如下(print-x three) 000会打印3个0字符这样我们就知道这个lambda数到底对应于自然数3了这和原始人在还没有数字概念的情况打绳结计数是一个道理加法定义如下(define (lmd-add a b)(lambda (f) (lambda (x)((a f) ((b f) x)))))测试下对不对(print-x (lmd-add two three)) 00000(print-x (add-1 (add-1 (add-1 (add-1 (add-1 zero)))))) 00000有兴趣的朋友还可以在这个基础上添加负数定义和加法运算。scheme能用一条规则推导出数字、四则运算符甚至条件语句、循环语句等等够原始吧原来在C语言中被我们看来是原子的数字、运算符、流程控制关键字都可以继续分解为更细的粒度例子中数字、加法都只不过是lambda演算漂亮的语法糖衣正如matrix 1中最后neo看透了世界的外表发现世界其实都是code。lisp不会衰落只能会进化因为他是数学家弄的一套数理逻辑一个图灵等价的lambda演算更直白一点讲就是用一种更简洁的方式定义了图灵机。更深层次上lisp代表了一种分析问题解决问题的思想它和C语言所基于的数学原理从最本质上来讲是完全一样的只是形式不同scheme要强力依赖递归形式其核心思想就是用简单的规则递归组合出复杂规则将复杂现象分析抽象成简单规则的递归这非常类似于人类大脑分析现实问题的模式如果大家非常感兴趣可以参看一本获普利策大奖的科普书《GEB一条永恒金带》这与类C的命令式语言强调模块治理的理念还是有很大差别的。我觉得lisp思想和分形很像其大量用于复杂问题求解上比如编译、定理证明等当然问题的层次化和模块化与事物简洁规则抽象上并不冲突相反这两种思想要在紧密配合才能将处理信息最小化解决问题方式最优化。另外lisp给我一个明显的提醒没有良好数学基础的程序员走不了多远大家可以看看《编程本质》这本书相信大家会理解这个观点。