为什么`(=(car x)' z)`有效?

时间:2014-12-30 15:58:23

标签: syntax lisp arc-lisp

当我对此感到困惑时,我在Arc教程中遇到了磕磕绊:

引自Arc Tutorial

  

与Common Lisp赋值一样,Arc' s =不仅适用于变量,而且适用于变量   可以到达内部结构。所以你可以用它来修改列表:

arc> x
(a b)
arc> (= (car x) 'z)
z
arc> x
(z b)

但是lisp是递归执行的,对吗?它说car返回列表中的第一个值。所以:

arc> (car x)
a

这是有道理的,但为什么不(= (car x) 'z)等于(= a 'z),这会导致:

arc> a
z
arc> x
(a b) ; Note how this hasn't changed

但它没有。相反,似乎(= (car x) 'z)似乎具有(= x (list 'z (car (cdr x))))

的效果
arc> (= x '(a b))
(a b)
arc> (= (car x) 'z)
z
arc> x
(z b)


...


arc> (= x '(a b))
(a b)
arc> (= x (list 'z (car (cdr x))))
(z b)
arc> x
(z b)

那么为什么(= (car x) 'z)确实以这种方式工作,我在这里失踪的是什么?


注意:这是我对LISP的第一次介绍。

4 个答案:

答案 0 :(得分:4)

=是一个特殊的操作符,它不是一个函数。因此,它的参数不会根据正常的递归过程进行评估。第一个参数是专门处理的,它标识了要分配的位置,而不是已经存在于该位置的值。它可能必须评估其中的子表达式以找到该位置,但一旦到达该位置,它就会停止评估。第二个参数将被正常评估,以获得分配值。

答案 1 :(得分:2)

=似乎是Arc中的赋值运算符,Common Lisp中的等价运算符为setf。在这种情况下,(car x)会返回要修改的地点

? (defparameter x '(a b))
X
? x
(A B)
? (setf (car x) 'z)
Z
? x
(Z B)

另见here

答案 2 :(得分:2)

=是一个宏或相当"特殊运算符",它只是内置宏的一个奇特名称。宏'参数(与函数'参数不同)根本没有被评估,因此=运算符得到(car x)未评估==>它得到了列表(car x)本身!现在,=运算符包含遍历列表(car x)的微型代码遍历器,并指出如果列表已被评估,将从哪个位置读取。并分配到那个地方。

它分配了什么?评估第二个参数的结果是,它手动评估一个参数。

因此=的有效评估方案实际上是

(= <unevaluated-argument> <evaluated-argument>)

编辑: 宏或特殊运算符的另一个示例是if。在(if <cond> <a> <b>)中,if开始首先评估并获得参数<cond><a><b> raw - 未评估。然后它手动评估<cond>并根据结果,评估<a><b>并返回结果。如果所有内容都是以递归方式进行评估的,那么您就永远无法使用ifcondloop或短路andor等等......

注意:=可能是(=我想)一个宏而不是特殊运算符,至少它在普通lisp中的等价setf是一个宏。我怀疑P. Graham将=直接嵌入到编译器中。但要知道它并不重要。

答案 3 :(得分:-1)

如果你有“ANSI Common Lisp”这本书,那么第3.3章就有这样的句子为什么Lisp没有指针:

  

理解Lisp的秘诀之一就是要意识到变量的值与列表中的元素相同。由于conses具有指向其元素的指针,因此变量具有指向其值的指针。

如果为x分配了一个列表:

arc> (= x '(a b))
(a b)

它就这样表达,变量x指向一个列表。列表的第一个位置指向符号a,第二个指向符号b:

A variable x points to a list, the 1st position points to symbol a and the 2nd position to symbol b

当x的汽车在(= (car x) 'z)中分配'z时,只需第一个位置指向新符号z。

enter image description here

最后,在表达式(= a 'z)中,赋值变量a,因此指向符号z

enter image description here