Lisp初学者。我正在读《常见的Lisp:一个温和的介绍》,我遇到了这种我不理解的行为。这是clisp:
[57]> (cdar '((fee fi) '(fo fum)))
(FI)
[58]> (cdar '('(fee fi) '(fo fum)))
((FEE FI))
第一个表达式(第57行)对我来说很有意义。它得到了((fee-fi)(fo-fum))的CAR的CDR,即(fee-fi)的CDR。但是58号线是怎么回事?我本以为它会给我同样的东西,(FI)。但它却给了我一份清单?有人能帮我了解发生了什么吗?
更令人惊讶的是,如果我用两个表达式来做每一个,当(fee fi)未被引用时,我会得到一个错误:
[72]> (car '((fee fi) '(fo fum)))
(FEE FI)
[73]> (cdr (FEE FI))
*** - EVAL: undefined function FEE
但当(费fi)被引用时,我得到了正确的结果,这与我的第一个结果相反:
[77]> (car '('(fee fi) '(fo fum)))
'(FEE FI)
[78]> (cdr '(FEE FI))
(FI)
任何照明都将不胜感激!
'
字符只是一个缩写:'something
在读取时扩展为(quote something)
。因此:
(cdar '('(fee fi) '(fo fum)))
实际上是:
(cdar (quote ((quote (fee fi)) (quote (fo fum)))))
第一个quote
阻止对其内容进行评估,因此其余部分只是文字列表和符号,因此更有用的表示方式是:
(cdar '((quote (fee fi)) (quote (fo fum))))
则CAR
是(quote (fee fi))
,而其中的CDR
是((fee fi))
。
在Lisp评估某个内容之前,必须先在中读取该内容Read
操作获取某个数据的文本表示,并将其转换为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
读取完所有内容后,将对结果进行评估。这是REPL中"read-eval-print loop"的"read-eval"部分。评估引用表单(quote ...)
的结果是它内部的内容。IOW顶部的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
,毫无疑问。