引用Common Lisp

Edw*_*rzo 3 lisp common-lisp

我最近开始学习lisp.我正在阅读Land of Lisp一书中的例子,我觉得我很清楚地理解了一切,直到我在第7章到达下面的例子:

(defun quote-it (x)
  (list 'quote x))
Run Code Online (Sandbox Code Playgroud)

现在,我知道list会创建一个带有参数的列表,就像在(list 1 2 3 4)评估列表中一样(1 2 3 4).

而且我也知道这quote允许我引用一个论点,就像我能做的那样'.所以'east是一样的(quote east)

现在,有趣的是,上面的函数不会返回一个列表,而只是引用我传递给它的任何内容.所以,如果我打电话给它

(quote-it east)它只会返回'east而不是('east)

如果我这样做了,我会把这个函数写成

(defun quote-it (x) 
  (quote x))
Run Code Online (Sandbox Code Playgroud)

所以,我不知道为什么我们写的命令,'quote(list 'quote x)从书的例子.

我知道我可以通过使用引号来切换代码和数据'(+ 1 2),但在这种情况下看起来我的目的是在这里实际应用quote函数.那么,为什么(list 'quote x)呢?

那么,有更多经验的人可以澄清一下吗?

Jos*_*lor 7

Lisp源代码由Lisp编程中使用的一些相同数据结构表示.这里特别重要的是列表和符号.当Lisp评估具有该表单的表单时

(quote something)
Run Code Online (Sandbox Code Playgroud)

也就是说,当Lisp评估一个列表并且其第一个元素是符号的表单时quote,它返回该对象something 而不进行评估.从而

(quote 2)       ;=> 2
(quote (a b c)) ;=> (a b c)
Run Code Online (Sandbox Code Playgroud)

现在,这就是评估者(或编译器,等)在获得Lisp对象进行评估时所做的事情恰好是第一个元素是符号的列表quote.作为Lisp 程序员,我们仍然需要编写 Lisp 读取器的代码来读取并传递给evalutor.我们可以写长格式

(quote 2)
(quote (a b c))
Run Code Online (Sandbox Code Playgroud)

在我们的源代码中,Lisp读者会读取它们并将它们传递给编译器,但我们是程序员,所以我们很懒,并且想避免一些打字.所以,我们可以输入

'2
'(a b c)
Run Code Online (Sandbox Code Playgroud)

代替.该编译器最终获得完全一样的输入; 一个列表,其第一个元素是符号quote,第二个值是2(a b c).

现在我们可以谈谈你的代码了.表格

(list 'quote x)
Run Code Online (Sandbox Code Playgroud)

返回一个列表,其第一个元素是符号quote,第二个元素是变量的值x.这可以打印

(quote <value-of-x>) ; fill in x's value for <value-of-x>, of course
Run Code Online (Sandbox Code Playgroud)

现在,Lisp打印机有点聪明,并且可以选择使用我们在编写源代码时允许使用的相同速记打印类似的东西.这样也可以打印成

'<value-of-x>
Run Code Online (Sandbox Code Playgroud)

现在我们已经足够解决有关该书代码的问题:

现在,有趣的是,上面的函数不会返回一个列表,而只是引用我传递给它的任何内容.所以,如果我打电话给它

(quote-it east)它只会返回'east而不是('east)

由于'east是缩写(quote east),我们现在看到它(quote-it east) 确实返回一个列表.它是您期望的表单列表:一个列表,其第一个元素是符号quote,第二个元素是符号east.如果它已经返回('east),它仍将返回一个列表,但它将返回错误表单的列表. ('east)当我们扩展缩写时,列表((quote east)); 也就是说,它是单个元素的列表,该元素是另一个列表,其第一个元素是符号quote,第二个元素是符号east.它肯定是一个列表,但它不是你要找的列表.

现在我们来看看你提出的代码.您的功能quote-it仅偶然发生在您正在呼叫的情况下(quote-it 'x).也就是说,你可以做到

(quote-it 'x)
;=> x
Run Code Online (Sandbox Code Playgroud)

但请注意,你正在获得一个符号,然后你就会得到这个符号x.你没有得到一个列表,其第一个元素是符号quote,第二个元素是<value-of-x>.当您使用quote-it其他值时,您将看到问题:

(quote-it 2)
;=> x
Run Code Online (Sandbox Code Playgroud)

仍然会得到一个符号,因为

(defun quote-it (x) 
  (quote x))         ; or 'x
Run Code Online (Sandbox Code Playgroud)

接受一个参数,将它绑定到词法变量x,然后返回值(quote x).有什么价值(quote x)?如前所述,当评价者(或编译器,& C.)获取符号的列表解释quotesomething,该值是文本something.由于正文quote-it是符号quote和符号的列表x,因此正文的值quote-it是符号x.