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

Aiv*_*var 8 lisp eval clojure

我正在学习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是否必不可少?

Die*_*lla 6

简短的回答是数字(例如符号和字符串)对自己进行评估.引用指示lisp(读者)在报价后面传递未评估的内容.eval然后在编写它时获取该列表,但没有引用,然后对其进行求值(在这种情况下(eval '(+ 3 4)),eval+通过两个参数计算函数call()).

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

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

  • 表单后跟的引号字符由读者转换为引用表单.'foo是(引用foo).读者不会"解释"引用.它只是转换引号字符 - 您可以直接编写引用表单.引用表单指示评估者(而不是读者!)按原样返回引用的值. (2认同)

ama*_*loy 4

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

因此,在运行 lisp 代码的正常过程中需要计算一个数字是非常自然的。为此,数字被定义为“对自身进行评估”,这意味着它们在评估后与之前相同:只是一个数字。该eval函数对编译3器在编译(例如,较大表达式(如(+ 5 3). 对于数字来说,这意味着不要管它。