我正在学习lisp并对一个简单的列表有疑问:
(setq stuff '(one two three (+ 2 2)))
stuff ; prints "one two three (+ 2 2)"
(setq stuff (list `one `two `three (+ 2 2)))
stuff ; prints "one two three 4"
第一个setq创建一个列表“one two three(+ 2 2)”。第二个列表创建“一二三四”。为什么第一个列表不评估(+ 2 2),但第二个列表没有?我在Emacs Lisp介绍文档中读到,当列表构建时,它从内到外进行评估。为什么第一个列表在将其添加到列表之前不评估添加?
这是emacs 24中的elisp。
答案 0 :(得分:8)
'
不等同于list
,它是quote
的简写。你真的是这样做的:
(setq stuff (quote (one two three (+ 2 2))))
引用的参数是表达式(one two three (+ 2 2))
。
来自http://www.gnu.org/software/emacs/manual/html_node/elisp/Quoting.html:“特殊形式引用返回其单个参数,如编写,未经评估”。
答案 1 :(得分:8)
看起来你正在研究Lisp的评估语义,所以继续玩吧!
您可以将quote
视为抑制其参数的评估。这允许您编写可以操作或传递的表达式。它还用于编写不应被评估为函数调用的数据结构。
数据结构:
'(1 2 3) ; => '(1 2 3)
(1 2 3) ; => Lisp error: (invalid-function 1)
;; The Lisp reader sees the number 1 in the function position and tries to call it, signalling an error.
语法转换:
(setq x '(string-to-int "123"))
(setf (car x) 'string-to-list)
x ; => '(string-to-list "123")
延迟评估:
(setq x '(message "Hello World")) ; => '(message "Hello World")
(eval x) ; => "Hello World"
有一个密切相关的特殊运算符,名为语法引用,使用反引号编写。它允许您使用逗号(,)运算符评估带引号的表达式中的各个表单。它就像quote
一样有一个逃生舱。
`(1 2 (+ 3 4)) ; => '(1 2 (+ 3 4))
`(1 2 ,(+ 3 4)) ; => '(1 2 7) ;; Note the comma!
语法quote还允许使用,@
语法列表拼接:
`(1 2 ,@(+ 3 4)) ; => '(1 2 + 3 4)
如您所见,它将后续表达式拼接到包含表达式中。在你开始编写宏之前,你可能不会经常看到它。
list
是一个简单的功能。它评估其参数,然后返回包含这些项的新数据结构。
(list 1 2 (+ 3 4)) ; => '(1 2 7)