显然' eval' CLISP中的引号符号

时间:2015-08-13 15:18:46

标签: lisp common-lisp 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),因此结果是一个列表,以listquote符号开头。这是让我困惑的第四个问题。为什么不返回(QUOTE (1 2 3))

我意识到如果你在REPL中输入(QUOTE '(1 2 3)),你会得到'(1 2 3),所以表达式在这个意义上是等价的。但是(LIST 1 2 3)相当于(1 2 3),但第一个表达式并没有返回。

(list 'quote 1 2 3)返回一个第一项为quote符号的列表似乎不一致,但(list 'quote (1 2 3))会返回引用列表。特别是因为像(list 'list ...)这样的表达似乎总是返回一个以符号开头的列表 - 到目前为止,至少quote是唯一的特殊情况'像这样。

这不是最容易表达的问题,所以我希望我能够解决这个问题。任何人都可以解释为什么报价会以这种看似独特的方式得到对待吗?

2 个答案:

答案 0 :(得分:5)

对于lisp阅读器,

'something(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。然而,读者可以阅读这些中的任何一个,并且它们将全部打印相同的例如。 '(1 . (2 . (3 . ()))) ==> (1 2 3)(+ . (2 . ( 3 . ()))) ; ==> 5

数字可以包含与所讨论数字之下的基数一样多的视觉形式。

(let ((*print-base* 16))
  (print 255)) ; prints FF (255 in hexadecimal)

list在Lisp中没有任何缩写或特殊性。它甚至不是一个原始的功能,但它非常有用,因为它消除了每次必须手工使用的不便。它可以这样定义:

(defun my-list (&rest lst)
  lst)

(my-list 1 2 3 4) ; ==> (1 2 3 4)

答案 1 :(得分:3)

请注意,REPL(READ-EVAL-PRINT-LOOP)有三件事:

  • 使用函数READ
  • 阅读
  • 使用函数EVAL
  • 进行评估
  • 并使用函数PRINT
  • 打印结果

要了解发生了什么,你必须查看所有三个功能。

让我们看一下第三种形式:

(list 'quote 1 2 3)

这是一个包含五个要素的列表:

  1. LIST
  2. (QUOTE QUOTE)
  3. 1
  4. 2
  5. 3
  6. EVAL然后计算参数,并使用四个结果调用函数list并返回一个新结果,一个包含四个元素的列表:

    1. QUOTE
    2. 1
    3. 2
    4. 3
    5. PRINT然后获取此列表并将其写为:(QUOTE 1 2 3)。没有缩写的方式来打印它。

      让我们看看第四种形式:

      (list 'quote '(1 2 3))
      

      这被视为三个元素的列表:

      1. LIST
      2. (QUOTE QUOTE)
      3. (QUOTE (1 2 3))
      4. eval使用两个参数调用list

        1. QUOTE
        2. (1 2 3)
        3. eval然后返回长度为二的列表:

          1. QUOTE
          2. (1 2 3)
          3. print现在可以通过两种不同的方式打印此列表:

            (QUOTE (1 2 3))或缩写形式'(1 2 3)。这里引号字符位于单个表达式的前面。

            您的实施使用了第一个版本。