2

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

引用自Arc 教程

像 Common Lisp 赋值一样,Arc 的 = 不仅用于变量,还可以到达内部结构。所以你可以用它来修改列表:

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

4 回答 4

4

=是一个特殊的运算符,它不是一个函数。所以它的参数不会根据正常的递归过程进行评估。第一个参数被特殊对待,它标识一个要分配的地方,而不是那个地方已经存在的值。它可能必须评估其中的子表达式才能找到该位置,但是一旦到达该位置,它就会停止评估。第二个参数将被正常评估,以获取要分配的值。

于 2014-12-31T19:32:40.937 回答
2

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

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

另请参见此处

于 2014-12-30T16:35:04.813 回答
2

=是一个宏或者更确切地说是“特殊运算符”,它只是内置宏的一个花哨的名称。宏的参数(与函数的参数不同)根本不求值,因此=运算符未求值(car x)==> 它得到的是列表(car x)本身!现在,该=运算符包含微型代码步行器,它遍历列表(car x)并计算出如果列表被评估将从哪个位置读取。并分配到那个地方。

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

所以有效的评估方案=实际上是

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

编辑:宏或特殊运算符的另一个示例是if. in (if <cond> <a> <b>),if开始首先被评估并获取 arguments <cond><a>并且<b>raw-未评估。然后它手动评估<cond>并根据结果,它要么评估<a>要么<b>返回结果。如果一切都真正递归评估,你永远不会有工作ifcondloop或短路and等等or......

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

于 2015-01-13T16:55:29.790 回答
-1

如果你有《ANSI Common Lisp》这本书,在第 3.3 章为什么 Lisp 没有指针有这样的句子:

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

如果 x 被分配一个列表:

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

它这样表述,变量 x 指向一个列表。列表的第 1 位指向符号 a,第 2 位指向符号 b:

变量 x 指向一个列表,第一个位置指向符号 a,第二个位置指向符号 b

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

在此处输入图像描述

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

在此处输入图像描述

于 2014-12-30T21:56:54.500 回答