gpt4 book ai didi

clojure - 为什么在 clojure 中 (eval (list + 1 2)) 和 (eval (list '+ 1 2)) 做同样的事情?

转载 作者:行者123 更新时间:2023-12-02 16:36:38 25 4
gpt4 key购买 nike

user=> (eval '(+ 1 2))
3
user=> (eval '('+ 1 2))
2
user=> (eval (list '+ '1 '2))
3
user=> (eval (list + '1 '2))
3

这是否意味着“+”有时与“+”相同?

是否有任何规则来确定应考虑什么情况?

最佳答案

(list '+ '1 '2)生成符号 + 的列表和数字12 。对其求值将查找由符号 + 命名的函数。并用参数 1 调用它和2 .

(list + '1 '2)生成由符号 + 命名的函数列表和数字12 。对其进行评估将使用列表其余部分的参数调用已经直接作为列表元素的函数。

顺便说一句,永远不需要引用数字。他们进行 self 评估。

编辑:

您在标题中没有提到的更有趣的情况是 (eval '('+ 1 2)) 中发生的情况。案件?为什么这不返回 3与其他情况一样,最终都会调用 + 命名的函数。参数 12

答案是不同,因为这次您引用了符号 +两次。因此,符号不会解析为其命名的函数,而是将符号本身作为函数调用。

现在,当符号作为函数调用时,会发生什么行为?它将其第一个参数视为映射,并将自身视为该映射中的键。但号码1显然不是 map ,所以它现在通常会返回 nil表示未找到匹配的 key 。

但在本例中,调用符号 + 有第二个参数。 ,第二个参数用作默认值,当找不到匹配的键时返回。这就是为什么形式 (eval '('+ 1 2))返回2 .

编辑 2:

好的,现在终于回答这个问题:为什么引用列表会产生与调用 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_ clojure.core$_PLUS_@165c64> 1 2)

您会看到第一种情况和第三种情况产生的打印结果相同,因为在这两种情况下您都引用了 +一次。在第二种情况下,+相反,被引用了两次,最后一次根本没有被引用。

编辑 3:

最后一个补充有望进一步澄清事情:除非它的第一个元素命名宏或特殊运算符,eval在评估列表本身之前,将递归评估列表的所有元素(包括第一个元素),方法是将其(已评估的)第一个参数作为函数调用,并将列表的其余部分作为参数。

如果第一个元素是 '+(quote +) (这是写同一事物的两种不同方式,引用的符号 + ),它将计算为符号 +这将被称为函数。

如果第一个元素是 + ,这将计算出实际的加法函数 ( clojure.core$_PLUS_ )。如果它已经是该函数,它将保持不变(基本上除了列表和符号之外的所有类型都是自评估的)。在这两种情况下,eval然后将调用该函数。

关于clojure - 为什么在 clojure 中 (eval (list + 1 2)) 和 (eval (list '+ 1 2)) 做同样的事情?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19111973/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com