1

我正在学习 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 创建一个列表“一二三 (+ 2 2)”。第二个列表创建“一二三 4”。为什么第一个列表不评估 (+ 2 2),但第二个列表呢?我在 Emacs Lisp 介绍文档中读到,在构建列表时,它会从内到外进行评估。为什么第一个列表在添加到列表之前不评估添加?

这是 emacs 24 中的 elisp。

4

2 回答 2

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:“特殊形式的引号返回其单个参数,如所写,而不对其进行评估”。

于 2012-12-31T22:08:04.100 回答
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!

语法引用还允许使用以下语法进行列表拼接,@

`(1 2 ,@(+ 3 4))   ; => '(1 2 + 3 4)

如您所见,它将后续表达式拼接到包含的表达式中。在您开始编写宏之前,您可能不会经常看到它。


list另一方面是一个简单的功能。它评估其参数,然后返回包含这些项目的新数据结构。

 (list 1 2 (+ 3 4)) ; => '(1 2 7)
于 2013-01-01T05:54:36.270 回答