在 Lisp 可以评估某些东西之前,必须先读入它。Read
operation 接受一些数据的文本表示并将其转换为 Lisp 数据。
[6]> (read)
'a ; I typed this
'A ; CLISP responded
[7]> (type-of *) ; * is previous-value
CONS
[8]> (mapcar #'print **) ; ** is value before previous value
QUOTE ; first element of the list (code form), (QUOTE A)
A ; second element of the list
'A ; CLISP translates (QUOTE A) back into 'A, for show
所以' ...
变成了(quote ...)
,一读。这是如何运作的?
[4]> (get-macro-character #\')
#<SYSTEM-FUNCTION SYSTEM::QUOTE-READER> ;
NIL
所以这句话背后有一些东西。一个quote-reader
系统函数。列表也很特别:
[5]> (get-macro-character #\()
#<SYSTEM-FUNCTION SYSTEM::LPAR-READER> ;
NIL
读取所有内容后,然后评估结果。这就是“read-eval-print loop”的“read-eval”部分,即 REPL。评估报价单的结果,是其中的任何内容。IOW 顶部消失了,但所有内部s 仍然存在。(quote ...)
quote
quote
没有报价,一切都会被评估。所以要评估,必须评估(cdr (FEE FI))
表单,如果它产生一个列表,则该列表将被返回。(FEE FI)
cdr
您可以尝试定义另一种表示文字数据的方式,例如用[ ... ]
括号表示(quote ( ... ))
。转换可以将内括号视为简单的括号。然后两者
> (cdar [(fee fi) (fo fum)])
> (cdar [[fee fi] [fo fum]])
正如您预期的那样,其行为将相同。
PS。CLHS 是您的朋友。
编辑:这是你犯错的地方。在你的最后一个例子中,
[77]> (car '('(fee fi) '(fo fum)))
'(FEE FI)
[78]> (cdr '(FEE FI))
(FI)
最后一次通话应该是
[1]> (cdr (quote '(FEE FI)))
((FEE FI))
放入表单'(FEE FI)
中会quote
阻止其评估,因此它按原样传递给cdr
. 以下是我们可以确定这一点的方法:
[2]> (car '('(fee fi) '(fo fum)))
'(FEE FI)
[3]> (cdr *) ; * is the last returned value
((FEE FI))
(cdr (car ...))
真的是 cdar
,毫无疑问。