我正在阅读Paul Graham的Lisots of Rop,他声称任何lisp功能都可以通过这7个基本功能的组合来构建:quote,atom,eq,cond,cons,car,cdr。
问题:Lisp方言真的完全基于这些功能吗?我们如何定义一笔“总和”?或者'加上'使用上述7个原始函数的函数?例如我们自己的(+ 1 2)功能
注意:我是Lisp的全新手,但我也开始对这种语言感到非常兴奋。这个问题的目的纯粹是真正的兴趣
答案 0 :(得分:12)
作者参考了图灵奖和Lisp发明人约翰麦卡锡“Recursive Functions of Symbolic Expressions and Their Computation by Machine”于1960年撰写的一篇非常着名的论文,其中他将Lisp的语义定义为一种新的计算形式,与图灵机相当。
在论文中(以及在Lisp 1.5 Manual中)麦卡锡描述了语言的解释器,这可以通过仅使用格雷厄姆提到的七个原始函数来完全编写。
该语言主要用于符号计算,而论文中提供的解释器仅涉及那些计算,而不依赖于与原子和对不同的数字或其他数据类型。
格雷厄姆在Lisp的第11页的一个注释中说,“有可能通过使用例如McCarthy 1960年的Lisp算术。一个 n 原子列表来表示数字 n “,因此执行求和只相当于附加两个列表。
当然,这种做法效率非常低:它仅用于表示与其他计算形式的等价性,而在真正的解释器/编译器中,整数表示为通常的,并且具有通常的运算符。
答案 1 :(得分:3)
据我记忆,还有一种方法可以使用列表嵌套级别来做到这一点(不记得,在哪里)。从()
开始为零,(())
== 1,依此类推。然后,您只需将inc
定义为list
,将dec
定义为car
:
CL-USER> (defun zero? (x) (eq () x))
ZERO?
CL-USER> (zero? nil)
T
CL-USER> (zero? 1)
NIL
CL-USER> (defparameter *zero* ())
*ZERO*
CL-USER> (defun inc (x) (list x))
INC
CL-USER> (defun dec (x) (car x))
DEC
CL-USER> (defun plus (x y)
(if (zero? y) x (plus (inc x) (dec y))))
PLUS
CL-USER> (plus *zero* (inc (inc *zero*)))
((NIL))
CL-USER> (defparameter *one* (inc *zero*))
*ONE*
CL-USER> (defparameter *two* (inc *one*))
*TWO*
CL-USER> (defparameter *three* (inc *two*))
*THREE*
CL-USER> (plus *two* *three*)
(((((NIL)))))
CL-USER> (equal *two* (dec (dec (dec (plus *two* *three*)))))
T
答案 2 :(得分:3)
<强> TL; DR:否。现代lisp系统比第一个lisp有更多的原语,每个新的原始数据类型都需要一个新的原语。
第一个Lisp没有数字,但是它已经完成了。这意味着它可以进行任何其他语言可能的任何计算,但这并不意味着这样做是可行的。数字并不难模仿,但计算速度很慢。今天有些人认为Lisp 1.5之前的算术速度很慢。
当我成为第一个口译员时,我不太关心数字。它并不是翻译的一个有趣的方面。然而,我确实以fibonacci
为例,这就是它的样子:
;; This is NOT Common Lisp code. It's Zozotez
(setq + (lambda (x y)
(if x (cons (car x)
(+ (cdr x) y))
y)))
(setq - (lambda (z w)
(if w (- (cdr z)
(cdr w))
z)))
(setq fibonacci
(lambda (n a1 a2)
(if n
(fibonacci (- n '(1))
a2
(+ a2 a1))
a1)))
(fibonacci '(1 1 1 1 1 1 1 1 1) () '(1))
; ==> (1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)
没有数字! (1
在我的语言中是一个符号,因此需要引用它,否则它将像变量一样被评估)
作为替代数字系统,我已经实现了一个位置系统,就像我们用相同的规则来编写数字来进行添加/乘法等等。也许比长度为n的lits要快但是要复杂得多。
如果Lisp有封闭,你可以做教堂数字。使用与lambda演算相同的方法,您可以使用闭包计算任何东西。您只需要一个原语lambda
。 (同样,不是最容易使用的)