简短回答绕过默认评估规则并执行not计算表达式(符号或 s-exp),并按照键入的方式将其传递给函数。
长答案:默认评估规则
当调用常规(我稍后会介绍)函数时,将评估传递给它的所有参数。这意味着你可以这样写:
(* (+ a 2)
3)
进而评估(+ a 2)
,通过评估a
2. 符号的值a
在当前变量绑定集中查找,然后替换。说a
当前绑定到值 3:
(let ((a 3))
(* (+ a 2)
3))
我们会得到(+ 3 2)
, + 然后在 3 和 2 上调用,产生 5。我们的原始形式现在是(* 5 3)
产量15。
Explain quote
已经!
好吧。如上所示,函数的所有参数都会被求值,因此如果您想传递symbol a
而不是它的价值,你不想评估它。 Lisp 符号可以兼作它们的值和在其他语言中使用字符串的标记,例如哈希表的键。
这是哪里quote
假设您想从 Python 应用程序绘制资源分配情况,而是在 Lisp 中进行绘制。让你的 Python 应用程序执行如下操作:
print("'(")
while allocating:
if random.random() > 0.5:
print(f"(allocate {random.randint(0, 20)})")
else:
print(f"(free {random.randint(0, 20)})")
...
print(")")
给你的输出看起来像这样(稍微漂亮一些):
'((allocate 3)
(allocate 7)
(free 14)
(allocate 19)
...)
记住我所说的quote
(“勾选”)导致默认规则不适用?好的。否则会发生的是allocate
and free
被查找,我们不希望这样。在我们的 Lisp 中,我们希望做到:
(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)
但是关于list
?
嗯,有时候你do想要评估这些论点。假设您有一个漂亮的函数,可以操作数字和字符串并返回结果的列表……。让我们先做一个错误的开始:
(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))
嘿!那不是我们想要的。我们想有选择地评估一些论点,并将其他论点保留为符号。尝试#2!
(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)
不只是quote
, But backquote
好多了!顺便说一句,这种模式在(大多数)宏中非常常见,因此有特殊的语法可以做到这一点。反引号:
(defun mess-with (number string)
`(value-of-number ,(1+ number) something-with-string ,(length string)))
这就像使用quote
,但可以选择通过在某些参数前加上逗号前缀来显式求值。结果相当于使用list
,但是如果您从宏生成代码,您通常只想计算返回的代码的一小部分,因此反引号更适合。对于较短的列表,list
可以更具可读性。
嘿,你忘了quote
!
那么,这会给我们带来什么影响呢?哦,对了,什么是quote
实际上呢?它只是返回未评估的参数!还记得我一开始所说的常规函数吗?事实证明,一些运算符/函数需要not评估他们的论点。例如 IF——如果 else 分支没有被采用,你不会希望它被评估,对吗?所谓的特殊操作员,与宏一起工作,就像这样。特殊运算符也是该语言的“公理”——最小的规则集——根据它,您可以通过以不同方式将它们组合在一起来实现 Lisp 的其余部分。
Back to quote
, 尽管:
Lisp> (quote spiffy-symbol)
SPIFFY-SYMBOL
Lisp> 'spiffy-symbol ; ' is just a shorthand ("reader macro"), as shown above
SPIFFY-SYMBOL
比较(在 Steel-Bank Common Lisp 上):
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]
因为没有spiffy-symbol
在目前的范围内!
加起来
quote
, backquote
(带逗号),以及list
是一些用于创建列表的工具,它们不仅仅是值列表,而且如您所见,可以用作轻量级(无需定义struct
) 数据结构!
如果你想了解更多,我推荐 Peter Seibel 的书实用 Common Lisp http://gigamonkeys.com/book如果您已经热衷于编程,可以了解学习 Lisp 的实用方法。最终,在您的 Lisp 之旅中,您也将开始使用包。罗恩·加勒特的Common Lisp 包白痴指南 http://www.flownet.com/ron/packages.pdf会给你很好的解释。
快乐黑客!