LISP 中引号的表观 'eval'
Apparent 'eval' of quote symbol in CLISP
CLISP REPL 的一些输出:
[1]> (list 'list 1 2 3)
(LIST 1 2 3)
[2]> (list 'list '(1 2 3))
(LIST (1 2 3))
[3]> (list 'quote 1 2 3)
(QUOTE 1 2 3)
[4]> (list 'quote '(1 2 3))
'(1 2 3)
前三个,我完全明白是怎么回事:list
函数被传递了一个符号('list
或'quote
),所以结果是一个以以下开头的列表list
或 quote
符号。这是第四个让我困惑的。为什么不 return (QUOTE (1 2 3))
?
我意识到如果你在 REPL 中输入 (QUOTE '(1 2 3))
,你会得到 '(1 2 3)
,所以从这个意义上说,表达式是等价的。但是 (LIST 1 2 3)
等同于 (1 2 3)
,但第一个表达式并不 return 那个。
似乎不一致 (list 'quote 1 2 3)
return 是第一项是 quote
符号的列表,但 (list 'quote (1 2 3))
return 是引用列表。特别是因为像 (list 'list ...)
这样的表达式似乎总是 return 以符号开头的列表 - 到目前为止,至少,quote
是唯一的 'special case' 这样的。
这不是最容易表达的问题,所以我希望我已经设法解决了我的困惑。谁能解释为什么报价会以这种看似独特的方式处理?
'something
与 lisp reader 的 (quote something)
相同。即使嵌套也会如此。我将在下一个表达式中加双引号,以便在评估后其中一个引号仍然存在。
当打印实现时,可以选择在有几种可能表示的情况下输出什么,因此一些实现会将 ''something
的评估打印为
(quote something)
而其他人可能会使用缩写 'something
.
'(quote 1 2 3)
不能缩写,因为引用形式只有一个参数。因此这里两个 lisp 系统都会打印 (quote 1 2 3)
.
这是查看您最后一个表情的方法:
(let ((data (list 'quote '(1 2 3))))
(format nil
"whole thing: ~a first element: ~a second-element: ~a"
data
(car data)
(cadr data)))
这将计算为 "whole thing: '(1 2 3) first element: QUOTE second-element: (1 2 3)"
或 "whole thing: (QUOTE (1 2 3)) first element: QUOTE second-element: (1 2 3)"
。
由于打印机永远不会看到输入是否被缩写,并且数据在内存中具有相同的结构,因此输出永远不会受到您输入数据的方式的影响。因此 (quote (quote (1 2 3)))
将打印与 ''(1 2 3)
.
相同的内容
您对 cons
个单元格有相同的行为,但标准规定了规则。 (cons 1 (cons 2 (cons 3 '())))
将是 (1 . (2 . (3 . ())))
但实际上只是打印 (1 2 3)
但是,如果你 (cons 1 2)
你会得到 (1 . 2)
表明 print
以不同的方式处理输出cdr
。但是 reader 可以读取其中任何一个,并且它们都将打印相同的内容,例如。 '(1 . (2 . (3 . ()))) ==> (1 2 3)
和 (+ . (2 . ( 3 . ()))) ; ==> 5
数字可以有与相关数字下方的碱基一样多的视觉形式。
(let ((*print-base* 16))
(print 255)) ; prints FF (255 in hexadecimal)
list
在 Lisp 中没有任何缩写或特殊性。它甚至不是一个原始函数,但它非常有用,因为它消除了每次都必须手动进行 cons 的不便。可以这样定义:
(defun my-list (&rest lst)
lst)
(my-list 1 2 3 4) ; ==> (1 2 3 4)
请注意,REPL(READ-EVAL-PRINT-LOOP)会做三件事:
- 使用函数读取
READ
- 使用函数求值
EVAL
- 并使用函数
PRINT
之类的东西打印结果
要了解发生了什么,您必须查看所有三个函数。
再来看第三种形式:
(list 'quote 1 2 3)
这是一个包含五个元素的列表:
LIST
(QUOTE QUOTE)
1
2
3
EVAL
然后计算参数,并用四个结果调用函数 list
和 returns 一个新结果,一个包含四个元素的列表:
QUOTE
1
2
3
PRINT
然后把这个列表写成:(QUOTE 1 2 3)
。没有简化的打印方式。
我们来看第四种形式:
(list 'quote '(1 2 3))
这被读取为三个元素的列表:
LIST
(QUOTE QUOTE)
(QUOTE (1 2 3))
eval
使用两个参数调用 list
:
QUOTE
(1 2 3)
eval
然后 returns 长度为二的列表:
QUOTE
(1 2 3)
print
现在可以用两种不同的方式打印此列表:
(QUOTE (1 2 3))
或缩写形式 '(1 2 3)
。这里一个引号字符在单个表达式的前面。
您的实现使用了第一个版本。
CLISP REPL 的一些输出:
[1]> (list 'list 1 2 3)
(LIST 1 2 3)
[2]> (list 'list '(1 2 3))
(LIST (1 2 3))
[3]> (list 'quote 1 2 3)
(QUOTE 1 2 3)
[4]> (list 'quote '(1 2 3))
'(1 2 3)
前三个,我完全明白是怎么回事:list
函数被传递了一个符号('list
或'quote
),所以结果是一个以以下开头的列表list
或 quote
符号。这是第四个让我困惑的。为什么不 return (QUOTE (1 2 3))
?
我意识到如果你在 REPL 中输入 (QUOTE '(1 2 3))
,你会得到 '(1 2 3)
,所以从这个意义上说,表达式是等价的。但是 (LIST 1 2 3)
等同于 (1 2 3)
,但第一个表达式并不 return 那个。
似乎不一致 (list 'quote 1 2 3)
return 是第一项是 quote
符号的列表,但 (list 'quote (1 2 3))
return 是引用列表。特别是因为像 (list 'list ...)
这样的表达式似乎总是 return 以符号开头的列表 - 到目前为止,至少,quote
是唯一的 'special case' 这样的。
这不是最容易表达的问题,所以我希望我已经设法解决了我的困惑。谁能解释为什么报价会以这种看似独特的方式处理?
'something
与 lisp reader 的 (quote something)
相同。即使嵌套也会如此。我将在下一个表达式中加双引号,以便在评估后其中一个引号仍然存在。
当打印实现时,可以选择在有几种可能表示的情况下输出什么,因此一些实现会将 ''something
的评估打印为
(quote something)
而其他人可能会使用缩写 'something
.
'(quote 1 2 3)
不能缩写,因为引用形式只有一个参数。因此这里两个 lisp 系统都会打印 (quote 1 2 3)
.
这是查看您最后一个表情的方法:
(let ((data (list 'quote '(1 2 3))))
(format nil
"whole thing: ~a first element: ~a second-element: ~a"
data
(car data)
(cadr data)))
这将计算为 "whole thing: '(1 2 3) first element: QUOTE second-element: (1 2 3)"
或 "whole thing: (QUOTE (1 2 3)) first element: QUOTE second-element: (1 2 3)"
。
由于打印机永远不会看到输入是否被缩写,并且数据在内存中具有相同的结构,因此输出永远不会受到您输入数据的方式的影响。因此 (quote (quote (1 2 3)))
将打印与 ''(1 2 3)
.
您对 cons
个单元格有相同的行为,但标准规定了规则。 (cons 1 (cons 2 (cons 3 '())))
将是 (1 . (2 . (3 . ())))
但实际上只是打印 (1 2 3)
但是,如果你 (cons 1 2)
你会得到 (1 . 2)
表明 print
以不同的方式处理输出cdr
。但是 reader 可以读取其中任何一个,并且它们都将打印相同的内容,例如。 '(1 . (2 . (3 . ()))) ==> (1 2 3)
和 (+ . (2 . ( 3 . ()))) ; ==> 5
数字可以有与相关数字下方的碱基一样多的视觉形式。
(let ((*print-base* 16))
(print 255)) ; prints FF (255 in hexadecimal)
list
在 Lisp 中没有任何缩写或特殊性。它甚至不是一个原始函数,但它非常有用,因为它消除了每次都必须手动进行 cons 的不便。可以这样定义:
(defun my-list (&rest lst)
lst)
(my-list 1 2 3 4) ; ==> (1 2 3 4)
请注意,REPL(READ-EVAL-PRINT-LOOP)会做三件事:
- 使用函数读取
READ
- 使用函数求值
EVAL
- 并使用函数
PRINT
之类的东西打印结果
要了解发生了什么,您必须查看所有三个函数。
再来看第三种形式:
(list 'quote 1 2 3)
这是一个包含五个元素的列表:
LIST
(QUOTE QUOTE)
1
2
3
EVAL
然后计算参数,并用四个结果调用函数 list
和 returns 一个新结果,一个包含四个元素的列表:
QUOTE
1
2
3
PRINT
然后把这个列表写成:(QUOTE 1 2 3)
。没有简化的打印方式。
我们来看第四种形式:
(list 'quote '(1 2 3))
这被读取为三个元素的列表:
LIST
(QUOTE QUOTE)
(QUOTE (1 2 3))
eval
使用两个参数调用 list
:
QUOTE
(1 2 3)
eval
然后 returns 长度为二的列表:
QUOTE
(1 2 3)
print
现在可以用两种不同的方式打印此列表:
(QUOTE (1 2 3))
或缩写形式 '(1 2 3)
。这里一个引号字符在单个表达式的前面。
您的实现使用了第一个版本。