user=> (eval '(+ 1 2))
3
user=> (eval '('+ 1 2))
2
user=> (eval (list '+ '1 '2))
3
user=> (eval (list + '1 '2))
3
这是否意味着“+有时从+一样吗?为什么在clojure(eval(list + 1 2))和(eval(list'+ 1 2))做同样的事情?
有什么规则来确定应考虑哪些情况?
user=> (eval '(+ 1 2))
3
user=> (eval '('+ 1 2))
2
user=> (eval (list '+ '1 '2))
3
user=> (eval (list + '1 '2))
3
这是否意味着“+有时从+一样吗?为什么在clojure(eval(list + 1 2))和(eval(list'+ 1 2))做同样的事情?
有什么规则来确定应考虑哪些情况?
(list '+ '1 '2)
产生符号列表+
和数字1
和2
。评估将查找由符号+
命名的函数和带参数1
和2
调用它。
(list + '1 '2)
产生由符号+
命名的功能以及编号1
和2
的功能列表。评估它将调用已经直接作为列表元素的函数,并使用来自列表其余部分的参数。
从未有必要引用的数字,顺便说一句。他们自我评估。
编辑:
更有趣的情况下,你没有在你的标题地址是在(eval '('+ 1 2))
情况下会发生什么?为什么会出现这种不返回3
像其他情况下,所有最终调用由+
的论据1
和2
命名的函数?
答案是,它是不同的,因为这个时候,你所引述的符号+
的两倍。因此,符号不会被解析为它所命名的函数,而是符号本身被称为函数。
现在什么是当一个符号被作为函数调用的行为?它将其第一个参数视为地图,并将其视为该地图中的关键字。但是号码1
显然不是地图,所以现在通常会返回nil
来指示找不到匹配的密钥。
在这种情况下,虽然,有第二个参数来调用符号+
,并且第二个参数被用作默认值时,没有发现匹配键返回。所以这就是为什么表格(eval '('+ 1 2))
返回2
。
编辑2:
OK,现在终于回答这个问题:为什么引用列表产生不同的结果不是调用list
功能具有相同的参数。这是因为报价'
停止它用在列表上的所有评价,但list
功能与他们产生一个列表作为元素之前评估其论点。
这些差异在打印各种形式,而不是直接发送到eval
的一切都变得很清楚:
user> '(+ 1 2)
(+ 1 2)
user> '('+ 1 2)
((quote +) 1 2)
user> (list '+ '1 '2)
(+ 1 2)
user> (list + '1 '2)
(#<core$_PLUS_ [email protected]> 1 2)
你看,第一和第三种情况产生打印同样的结果,因为在这两种这些案例你曾经引用过+
。在第二种情况下,+
是引用而不是两次,并在最后它不是在所有的报价。
编辑3:
最后一个除了应该有希望进一步澄清的事情:除非它的第一个元素名称的宏或特殊的运算符,eval
将递归评估列表中的所有元素(包括第一)前通过将其(被评估的)第一个参数作为函数与列表的其余部分作为参数来评估列表本身。
如果第一个元素是'+
或(quote +)
(这些都写一样的东西,所引用的符号+
两种不同的方式),将评估的符号+
,并且将被称为功能。
如果第一个元素是+
,那么将评估为实际加法函数(clojure.core$_PLUS_
)。如果它已经是该功能,它将保持不变(除了列表和符号之外,基本上所有类型都是自我评估的)。在这两种情况下,eval
都会调用该函数。