引用clojure导致非评估。 ':a
和:a
会返回相同的结果。 ':a和:a之间有什么区别?一个未被评估,其他评估自己......但是与非评估相同吗?
答案 0 :(得分:21)
':a
是(quote :a)
的缩写。
(eval '(quote form))
按定义返回form
。也就是说,如果Clojure函数eval
接收一个列表结构作为其参数,其第一个元素是符号quote
,它返回所述列表结构的第二个元素,而不以任何方式对其进行转换(因此据说所引用的表格未经评估)。换句话说,行为eval
在其参数是(quote foo)
形式的列表结构时调度,即返回foo
不变,无论它是什么
当您在程序中记下文字:a
时,它会在中读取关键字:a
;也就是说,具体的文本:a
被转换为内存中的数据结构,恰好称为:a
关键字(Lisp是homoiconic意味着偶尔很难区分文本表示Lisp数据和数据本身,即使这对解释目的有用......)。
对应于文字:a
的内存数据结构是一个Java对象,它暴露了许多方法等,并且具有函数eval
的有趣属性,当它接收此数据对象作为参数,不加改变地返回它。换句话说,您询问的关键字“对自身的评价”只是在将关键字作为参数传递时调度的行为eval
。
因此当eval
看到':a
时,它会将其视为带引号的形式并返回其第二部分,恰好是:a
。另一方面,当eval
看到:a
时,它会将其视为关键字并将其保持不变。两种情况下的返回值都是相同的(它只是关键字:a
);评估过程略有不同。
Clojure语义 - 对于Lisp的任何方言,确实是Lisp语义 - 根据函数eval
在接收各种Lisp数据结构时返回的值和副作用来指定作为参数。因此,上面解释了当你在程序中写下':a
或:a
时实际意味着什么(像(println :a)
这样的代码可能被编译成有效的字节码而不实际编码函数{ {1}}当然;但是语义总是被保留,所以它仍然像 那样行为eval
接收包含符号eval
的列表结构关键字println
)。
这里的关键思想是,无论被评估的表单是:a
还是':a
,关键字数据结构都是在读取时构建的;然后,当评估其中一个表格时,该数据结构将保持不变 - 尽管出于不同的原因。