我正在学习Clojure,并试图通过绘制与Python相似的功能来理解reader、quoting、eval和homoiconicity。
在Python中,避免(或推迟)求值的一种方法是将表达式放在引号之间,例如。'3 + 4'。您可以稍后使用eval对其进行评估,例如。产生7的eval('3 + 4')。(如果只需要引用Python值,可以使用repr函数,而不是手动添加引用。)
在Lisp中,你用quote或'来表示引号,用eval来表示求值。产生7的(eval '(+ 3 4))。
因此,在Python语言中,“引用”的内容由一个字符串表示,而在Lisp语言中,它由一个列表表示,该列表的第一项是quote。
最后,我的问题是:尽管没有引用3,为什么Clojure允许使用(eval 3)?这仅仅是Lisp风格的问题(尽可能给出答案而不是错误),还是有其他原因?这种行为对Lisp来说是必要的吗?
发布于 2012-12-27 09:58:14
其他答案已经解释了这些机制,但我认为哲学观点是lisp和python看待“代码”的不同方式。在python中,表示代码的唯一方法是字符串,所以尝试计算非字符串当然会失败。Lisp具有更丰富的代码数据结构:列表、数字、符号等等。因此,表达式(+ 1 2)是一个列表,包含一个符号和两个数字。在计算列表时,必须首先计算它的每个元素。
因此,在运行lisp代码的普通过程中需要计算一个数字是很自然的。为此,数字被定义为“评估自己”,这意味着它们在评估后与之前相同:只是一个数字。eval函数对空的“代码片段”3应用相同的规则,编译器在编译更大的表达式(比如(+ 5 3) )的第三个元素时也会应用这些规则。对于数字来说,这意味着不要去管它。
发布于 2012-12-27 08:53:06
简而言之,数字(和符号,以及字符串)会自动求值。引用指示lisp (阅读器)传递引用后未计算的任何内容。然后,eval获得您编写的列表,但不带引号,然后对其求值(对于(eval '(+ 3 4)),eval将通过两个参数对函数调用(+)求值)。
最后一个表达式的结果如下所示:
eval)和一些参数。(+ 3 4)列表)。(+ 3 4)的eval函数调用为argument.eval函数再次执行相同的步骤,找到普通函数+和参数,并应用它,获得结果。发布于 2012-12-27 09:30:48
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方言定义了所有数据类型(列表和符号除外)都是自我评估的。
https://stackoverflow.com/questions/14048041
复制相似问题