何时使用';(或引用)在Lisp中?

何时使用';(或引用)在Lisp中?,lisp,quote,Lisp,Quote,在读完了一本介绍性的Lisp书籍的主要部分后,我仍然无法理解特殊运算符(quote)(或等效的“)函数的作用,但我所看到的Lisp代码中都有这种情况 它做什么?上面写着“不要评价我”。例如,如果您想将列表用作数据,而不是代码,则应在其前面加上引号。比如说, (打印“(+34))打印“(+34)”,而 (print(+34))打印“7”它说“不要评估我”。例如,如果您想将列表用作数据,而不是代码,则应在其前面加上引号。比如说, (打印“(+34))打印“(+34)”,而 (print(+34))打

在读完了一本介绍性的Lisp书籍的主要部分后,我仍然无法理解特殊运算符
(quote)
(或等效的
)函数的作用,但我所看到的Lisp代码中都有这种情况

它做什么?

上面写着“不要评价我”。例如,如果您想将列表用作数据,而不是代码,则应在其前面加上引号。比如说,

(打印“(+34))
打印“(+34)”,而
(print(+34))
打印“7”

它说“不要评估我”。例如,如果您想将列表用作数据,而不是代码,则应在其前面加上引号。比如说,

(打印“(+34))
打印“(+34)”,而
(print(+34))
打印“7”

引号阻止表单的执行或求值,将表单转换为数据。通常,您可以通过评估数据来执行数据

quote创建列表数据结构,例如,以下数据结构等效:

(quote a)
'a
它还可用于创建列表(或树):


您最好在lisp上获得一本介绍性的书,例如(可在线阅读)。

引用阻止表单的执行或评估,将表单转换为数据。通常,您可以通过评估数据来执行数据

quote创建列表数据结构,例如,以下数据结构等效:

(quote a)
'a
它还可用于创建列表(或树):


你最好能得到一本关于lisp的入门书,比如(可以在线阅读)。

这个问题的一个答案是引用“创建列表数据结构”。这不太正确。引用比这更重要。事实上,QUOTE是一个微不足道的操作符:它的目的是防止任何事情发生。特别是,它没有创造任何东西

(引用X)所说的基本上是“什么都不要做,给我X”X不必是(引用a B C)中的列表或(引用FOO)中的符号。它可以是任何物体。事实上,(list’QUOTE SOME-OBJECT)生成的列表的求值结果总是返回SOME-OBJECT,不管它是什么

现在,(QUOTE(abc))似乎创建了一个元素为A、B和C的列表,原因是这样一个列表实际上就是它返回的内容;但是在评估报价表单时,列表通常已经存在了一段时间(作为报价表单的一个组件!),由加载程序或读取器在执行代码之前创建


这样做的一个含义是,修改报价表单返回的列表是非常不明智的,这往往会让新手绊倒。出于所有目的,QUOTE返回的数据将被视为正在执行的代码的一部分,因此应被视为只读

这个问题的一个答案是引用“创建列表数据结构”。这不太正确。引用比这更重要。事实上,QUOTE是一个微不足道的操作符:它的目的是防止任何事情发生。特别是,它没有创造任何东西

(引用X)所说的基本上是“什么都不要做,给我X”X不必是(引用a B C)中的列表或(引用FOO)中的符号。它可以是任何物体。事实上,(list’QUOTE SOME-OBJECT)生成的列表的求值结果总是返回SOME-OBJECT,不管它是什么

现在,(QUOTE(abc))似乎创建了一个元素为A、B和C的列表,原因是这样一个列表实际上就是它返回的内容;但是在评估报价表单时,列表通常已经存在了一段时间(作为报价表单的一个组件!),由加载程序或读取器在执行代码之前创建


这样做的一个含义是,修改报价表单返回的列表是非常不明智的,这往往会让新手绊倒。出于所有目的,QUOTE返回的数据将被视为正在执行的代码的一部分,因此应被视为只读

简短回答 绕过默认求值规则,不求值表达式(symbol或s-exp),将其完全按类型传递给函数

长答案:默认评估规则

当调用一个常规函数(我稍后会谈到这个)时,传递给它的所有参数都会被求值。这意味着您可以这样写:

(* (+ a 2)
   3)
然后通过计算
a
和2来计算
(+a2)
。符号
a
的值在当前变量绑定集中查找,然后替换。假设
a
当前绑定到值3:

(let ((a 3))
  (* (+ a 2)
     3))
我们将得到
(+32)
,然后在3和2上调用+得到5。我们原来的表单现在是
(*53)
15

解释
报价
已经

好的。如上所述,函数的所有参数都会求值,因此,如果希望传递符号
a
,而不是其值,则不希望求值。Lisp符号可以同时用作其值和标记,在其他语言中,您可能会使用字符串,例如哈希表的键

这就是
quote
的用武之地。假设您希望从Python应用程序绘制资源分配,而不是在Lisp中绘制。让您的Python应用程序执行以下操作:

打印(“(”)
分配时:
如果random.random()大于0.5:
打印(f“(分配{random.randint(0,20)})”
其他:
打印(f)(自由{random.randint(0,20)})
...
打印(“”)
让您的输出看起来像这样(稍微修饰):

还记得我所说的导致默认规则不适用的
引号
(“勾选”)吗?好。否则会发生的情况是,
al的值
'((allocate 3)
  (allocate 7)
  (free 14)
  (allocate 19)
  ...)
(dolist (entry allocation-log)
  (case (first entry)
    (allocate (plot-allocation (second entry)))
    (free (plot-free (second entry)))))
(plot-allocation 3)
(plot-allocation 7)
(plot-free 14)
(plot-allocation 19)
(defun mess-with (number string)
  '(value-of-number (1+ number) something-with-string (length string)))

Lisp> (mess-with 20 "foo")
(VALUE-OF-NUMBER (1+ NUMBER) SOMETHING-WITH-STRING (LENGTH STRING))
(defun mess-with (number string)
  (list 'value-of-number (1+ number) 'something-with-string (length string)))

Lisp> (mess-with 20 "foo")
(VALUE-OF-NUMBER 21 SOMETHING-WITH-STRING 3)
(defun mess-with (number string)
  `(value-of-number ,(1+ number) something-with-string ,(length string)))
Lisp> (quote spiffy-symbol)
SPIFFY-SYMBOL

Lisp> 'spiffy-symbol ; ' is just a shorthand ("reader macro"), as shown above
SPIFFY-SYMBOL
Lisp> spiffy-symbol
debugger invoked on a UNBOUND-VARIABLE in thread #<THREAD "initial thread" RUNNING   {A69F6A9}>:
  The variable SPIFFY-SYMBOL is unbound.

Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
  0: [ABORT] Exit debugger, returning to top level.

(SB-INT:SIMPLE-EVAL-IN-LEXENV SPIFFY-SYMBOL #<NULL-LEXENV>)
0] 
(define atom?              ; defining a procedure atom?
  (lambda (x)              ; which as one argument x
(and (not (null? x)) (not(pair? x) )))) ; checks if the argument is atom or not
(atom? '(a b c)) ; since it is a list it is false #f
This special form returns object, without evaluating it. 
(quote (+ 1 2))
     ⇒ (+ 1 2)

(quote foo)
     ⇒ foo

'foo
     ⇒ foo

''foo
     ⇒ (quote foo)

'(quote foo)
     ⇒ (quote foo)
`(a list of (+ 2 3) elements)
     ⇒ (a list of (+ 2 3) elements)

'(a list of (+ 2 3) elements)
     ⇒ (a list of (+ 2 3) elements)
`(a list of ,(+ 2 3) elements)
     ⇒ (a list of 5 elements)
`(1 2 (3 ,(+ 4 5)))
     ⇒ (1 2 (3 9))
(setq some-list '(2 3))
     ⇒ (2 3)

(cons 1 (append some-list '(4) some-list))
     ⇒ (1 2 3 4 2 3)

`(1 ,@some-list 4 ,@some-list)
     ⇒ (1 2 3 4 2 3)
class Symbol:
   def __init__(self,name,code,value):
       self.name=name
       self.code=code
       self.value=value
(progn
  (fset 'add '+ )
  (set 'add 2)
  (add add add)
)
(add add add)
(+ add add)
(+ 2 add)
(+ 2 2)
4
Code is data and data is code.  There is no clear distinction between them.
1 ]=> '(+ 2 3 4)
;Value: (+ 2 3 4)

1 ]=> (+ 2 3 4)
;Value: 9
1 ]=> 'code
;Value: code

1 ]=> '10
;Value: 10

1 ]=> '"ok"
;Value: "ok"

1 ]=> code
;Unbound variable: code