为什么Clojure允许(eval 3)虽然没有引用3?

时间:2012-12-27 00:40:25

标签: clojure lisp eval

我正在学习Clojure并尝试通过与Python的类似功能相似来理解读者,引用,评估和同质性。

在Python中,避免(或推迟)评估的一种方法是将表达式包装在引号之间,例如。 '3 + 4'。您可以稍后使用eval对此进行评估,例如。 eval('3 + 4')屈服7。 (如果只需要引用Python值,可以使用repr函数而不是手动添加引号。)

在Lisp中,您使用quote'进行引用,使用eval进行评估,例如。 (eval '(+ 3 4))屈服于7

因此在Python中,“引用”的东西由字符串表示,而在Lisp中,它由以quote作为第一项的列表表示。

我的问题,最后:为什么Clojure允许(eval 3)虽然没有引用3?这只是Lisp风格的问题(试图尽可能给出答案而不是错误)或者还有其他原因吗?这种行为对Lisp是否必不可少?

4 个答案:

答案 0 :(得分:6)

简短的回答是数字(以及符号和字符串)对自己进行评估。引用指示lisp(读者)在报价后面传递未评估的内容。 eval然后在编写时获取该列表,但没有引号,然后对其进行评估(在(eval '(+ 3 4))的情况下,eval将评估函数调用(+ )超过两个论点)。

最后一个表达式会发生以下情况:

  1. 当您按Enter键时,将评估表达式。它包含一个普通的函数调用(eval)和一些参数。
  2. 评估参数。第一个参数包含一个引用,它告诉读者生成引用后的内容(实际的(+ 3 4)列表)。
  3. 没有更多参数,并且会评估实际的函数调用。这意味着使用列表 eval作为参数调用(+ 3 4)函数。
  4. eval函数再次执行相同的步骤,找到正常函数+和参数,并应用它,获得结果。

答案 1 :(得分:4)

其他答案已经解释了这些机制,但我认为哲学观点在于lisp和python以不同的方式看待"代码"。在python中,表示代码的唯一方法是作为字符串,因此当然尝试评估非字符串将失败。 Lisp为代码提供了更丰富的数据结构:列表,数字,符号等。所以表达式(+ 1 2)是一个列表,包含一个符号和两个数字。评估列表时,必须首先评估每个元素。

因此,在运行lisp代码的普通过程中需要评估一个数字是很自然的。为此,数字被定义为"评估自己",意味着它们在评估之后与之前相同:只是一个数字。 eval函数将相同的规则应用于裸#34;代码段"编译器在编译时会应用3,例如,像(+ 5 3)这样的较大表达式的第三个元素。对于数字,这意味着不管它。

答案 2 :(得分:3)

3应该评估什么? Lisp最有意义的是评估一个数字。我们是否要求在代码中引用数字?这不是非常方便而且极其成问题:

而不是

(defun add-fourtytwo (n)
   (+ n 42))

我们必须写

(defun add-fourtytwo (n)
   (+ n '42))

代码中的每个数字都需要引用。缺少引用会触发错误。这不是人们想要使用的东西。

作为旁注,想象一下当您想在代码中使用eval时会发生什么。

(defun example ()
  (eval 3))

以上是错的。需要引用数字。

 (defun example ()
   (eval '3))

上面没问题,但在运行时会产生错误。 Lisp将'3评估为数字3.但是然后在数字上调用eval将是一个错误,因为它们需要被引用。

所以我们需要写:

(defun example ()
   (eval ''3))

这不是很有用......

在Lisp历史中,数字总是自我评估。但在早期的Lisp实现中,一些其他数据对象(如数组)不能自我评估。同样,由于这是一个巨大的错误来源,像Common Lisp这样的Lisp方言已经定义了所有数据类型(列表和符号除外)都是自我评估的。

答案 3 :(得分:2)

要回答这个问题,我们需要查看lisp中的eval定义。例如。在CLHS中有定义:

  

语法:eval form =>结果*

     

参数和价值观:   形式 - 形式   结果 - 表格评估产生的价值。

form

的位置
  
      
  1. 任何要评估的对象。
  2.   
  3. 符号,复合形式或自我评估对象。
  4.   
  5. (对于运营商,如<<operator>> form'') a compound form having that operator as its first element.报价单中的表格   常数形式。''
  6.   

在您的情况下,数字“3”为self-evaluating objectSelf-evaluating objecta form that is neither a symbol nor a cons is defined to be a self-evaluating object。我相信对于clojure,我们可以在此定义中将cons替换为list

在clojure中,lists只将eval解释为函数调用。其他数据结构和对象被评估为自我评估对象。

'(+ 3 4)等于(list '+ 3 4)'(由读者转换为quote函数)只是避免评估给定的形式。因此,在表达式(eval '(+ 3 4)) eval中,将列表数据结构('+ 3 4)作为参数。