使其通过一个入门的Lisp书的主要部分后,我还是弄不明白什么特殊的运算符(quote)
(或同等学历'
)函数,然而这已经遍布我见过Lisp代码。
它有什么作用?
使其通过一个入门的Lisp书的主要部分后,我还是弄不明白什么特殊的运算符(quote)
(或同等学历'
)函数,然而这已经遍布我见过Lisp代码。
它有什么作用?
简短的回答绕过默认的评价规则, 不计算表达式(符号或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。
解释quote
到了!
好的。 从上面可以看出,所有参数的函数进行评估,因此,如果您想通过符号 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(")")
给你输出看起来像这样(略prettyfied):
'((allocate 3)
(allocate 7)
(free 14)
(allocate 19)
...)
还记得我说过quote
(“嘀”)引起的默认规则不适用? 好。 什么会发生,否则是值allocate
和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
?
嗯,有时候你想评价的参数。 假设你有一个漂亮的函数操纵数字和字符串并返回所得到的......事情的清单。 让我们做一个错误的开始:
(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
,但是backquote
好多了! 顺便说一句,这种模式是在(主要是)宏如此普遍,有这样做只是特殊的语法。 反引号:
(defun mess-with (number string)
`(value-of-number ,(1+ number) something-with-string ,(length string)))
这就像使用quote
,但与选项用逗号前缀来明确地评估一些参数。 其结果是相当于使用list
,但如果你从宏生成的代码,你往往只想要的代码返回来评价一小部分,所以反引号更适合。 对于较短的名单, list
可以更具可读性。
嘿,你忘了关于quote
!
所以,这给我们? 哦,对了,这是什么quote
实际上做? 它只是返回其参数(一个或多个)未评估! 记得我在有关正函数的开头说的吗? 原来,一些运营商/函数需要不评估他们的论点。 比如如果 - 你不会想如果它不采取进行评估else分支,对不对? 所谓的特殊运营商 ,与宏携手,这样的。 特种作业人员也是语言的“公理” - 最小的一套规则 - 在你可以通过它们以不同的方式结合在一起实现的Lisp的其余部分。
返回quote
,但:
Lisp> (quote spiffy-symbol)
SPIFFY-SYMBOL
Lisp> 'spiffy-symbol ; ' is just a shorthand ("reader macro"), as shown above
SPIFFY-SYMBOL
比较(上钢银行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
)数据结构!
如果您想了解更多,我建议彼得·塞贝尔的书实用的Common Lisp的一个实用的方法来学习Lisp的,如果你已经进入编程在逃。 最终,在你的Lisp的旅程,您将开始使用包了。 罗恩·加勒特是白痴指南Common Lisp的软件包会给你那些很好的解释。
快乐的黑客攻击!
它说:“不评价我。” 例如,如果你想使用一个列表数据,而不是代码,你就会把报价在它的前面。 例如,
(print '(+ 3 4))
打印“(+ 3 4)”,而(print (+ 3 4))
输出“7”
其他人都极好地回答了这个问题,和马提亚Benkard带来了一个很好的警示。
不要使用QUOTE创建列表,你将在以后修改。 该规范允许编译器把报名单为常数。 通常,编译器将通过在存储器中创建用于它们的单个值,然后从引用的所有位置其中常数似乎单个值优化常数。 换句话说,它可以像对待一个匿名的全局变量不变。
这可能会导致明显的问题。 如果你修改一个常数,它很可能修改同常数的其他用途中完全不相关的代码。 例如,你可以比较的一些变量“的一些功能(11),和在一个完全不同的功能,开始与列表”(11),然后添加更多的东西给它。 一旦运行这些功能,你可能会发现第一个功能不符合正常的事情了,因为它现在试图将变量比较“(1 1 2 3 5 8 13),这是第二个函数返回什么。 这两个功能是完全无关的,但他们有因为使用常量对彼此的影响。 更疯狂的不良影响可能发生,就像一个完全正常的列表迭代突然无限循环。
当你需要一个恒定的列表,如对比用报价。 使用列表时,你会被修改的结果。
一个回答这个问题说QUOTE“创建列表数据结构”。 这是不完全正确。 报价比这更重要。 其实,报价是一个微不足道的操作:它的目的是防止任何事情的发生都没有。 特别是,它不会产生任何东西。
什么(报价X)说基本上是“没有做任何事情,只要给我X” X不一定是列表中(报价(ABC))或符号作为(报价FOO)。 它可以是任何对象什么的。 事实上,评估是由(LIST“引用一些对象)产生的列表的结果将永远只是返回一些对象,不管它是什么。
现在,之所以说(行情(ABC))好像它创造的元素是A,B和C是这样一份清单确实是它返回一个列表; 但在QUOTE形式进行评价的时候,该列表已普遍已经存在了一段时间(如在QUOTE形式的组分!),创建或者由装载机或读取器之前的代码的执行。
这方面的一个暗示,往往相当频繁绊倒新手是,它是非常不明智的修改通过报价的形式返回一个列表。 通过报价返回的数据,对所有意图和目的,要为被执行的代码的一部分考虑,因此应被视为只读!
报价防止执行或评价的形式,将其代替为数据。 一般来说,你可以再eval'ing执行其中的数据。
报价创建列表数据结构,例如,下面的是等价的:
(quote a)
'a
它也可以用来创建列表(或树):
(quote (1 2 3))
'(1 2 3)
你可能最好关闭得到一个introductary书口齿不清,如实用的Common Lisp (这是提供给在网上阅读)。
当我们想传递一个论点本身,而不是传递参数的值,那么我们就用引号。 它主要使用列表,对的,哪些是不是在C编程语言提供原子时(大多数人用C编程开始编程,因此,我们会感到困惑)这是Scheme编程语言的代码是口齿不清的一种方言相关程序传球我想你可以理解这段代码。
(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
最后一行(原子?“ABC)被传递ABC,因为它是该过程检查是否ABC是原子或没有,但是当你经过(原子?ABC)然后它检查ABC的值和passses的值以它。 因为,我们没有提供任何价值,它
在的Emacs Lisp:
有什么可以被引用?
列表和符号。
引用的数的计算结果为数字本身: '5
是相同的5
。
当你引用列表会发生什么?
例如:
'(one two)
的计算结果为
(list 'one 'two)
其计算为
(list (intern "one") (intern ("two")))
(intern "one")
创建一个名为在“中央”哈希映射“一”,并将其存储象征,所以任何时候你说'one
则名为符号"one"
将在中央哈希地图抬头。
但究竟什么是象征?
例如,在OO-语言(Java /使用Javascript / Python)的符号可以表示为一个对象,该对象具有name
字段,它是符号的名字等"one"
的上方,以及数据和/或代码可以和它关联的这个对象。
所以在Python的符号可以被实现为:
class Symbol:
def __init__(self,name,code,value):
self.name=name
self.code=code
self.value=value
在的Emacs Lisp例如一个符号可以具有1)与它(在同一时间相关联的数据 - 对于相同的符号)2)与之相关联的代码 - 取决于上下文,数据或者代码被调用。
例如,在elisp的:
(progn
(fset 'add '+ )
(set 'add 2)
(add add add)
)
计算结果为4
。
因为(add add add)
的计算结果为:
(add add add)
(+ add add)
(+ 2 add)
(+ 2 2)
4
因此,举例来说,使用Symbol
我们在上述的Python定义的类,这add
elisp的码元可在Python作为被写入Symbol("add",(lambda x,y: x+y),2)
非常感谢IRC上#emacs乡亲向我解释的符号和报价。
引用返回它的参数的内部表示。 通过这样的报价是什么没有做过多的解释犁地之后,这是当电灯泡继续。 如果REPL没有函数名转换为大写时,我引用了他们,它可能没有我恍然大悟。
所以。 普通Lisp函数转换其参数为内部表示,评估的参数,并应用功能。 引用其参数转换为内部表示,只是返回。 从技术上讲它是正确的说帖指出,“不评价”,但是当我试图理解它的所作所为,告诉我什么没有做令人沮丧。 我的烤面包机无法评估Lisp函数要么; 但是这不是你如何解释一个烤面包机做什么。
Anoter简短的回答:
quote
是指未经评估它, 反引号是报价,但留下后门 。
一个很好的参考:
的Emacs Lisp参考手册非常清楚
9.3报价
特殊形式报价返回其单个参数,如写的,没有计算它。 这提供了一种方法,包括常量符号和列表,这是不是自我评估的对象,在程序中。 (这是没有必要引用自评价对象,诸如数字,字符串,和载体。)
特殊形式:报价对象
This special form returns object, without evaluating it.
由于报价是经常用到的程序,Lisp语言为它提供一个方便的读取语法。 一个撇号字符(“”'),接着一个Lisp对象(在读语法)膨胀到其第一个元素是报价,并且其第二元件是对象的列表。 因此,所读取的语法“x是(报价X)的缩写。
下面是使用引号表达式的一些例子:
(quote (+ 1 2))
⇒ (+ 1 2)
(quote foo)
⇒ foo
'foo
⇒ foo
''foo
⇒ (quote foo)
'(quote foo)
⇒ (quote foo)
9.4反引号
反引号结构允许你引用一个列表,但选择性地评估该列表的元素。 在最简单的情况下,它是相同的特殊形式引号(在上一节中描述的;另见引用)。 例如,这两种形式得到相同的结果:
`(a list of (+ 2 3) elements)
⇒ (a list of (+ 2 3) elements)
'(a list of (+ 2 3) elements)
⇒ (a list of (+ 2 3) elements)
的参数反引号内的特殊标记物“”指示的值不是常数。 该的Emacs Lisp评估评估的参数“”,并把该值列表中的结构:
`(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)