gpt4 book ai didi

clojure - 不断地发挥作用在语法引用中不起作用

转载 作者:行者123 更新时间:2023-12-05 02:23:17 26 4
gpt4 key购买 nike

如果我这样做:

(eval (let [f (fn [& _] 10)]
`(~f nil)))

它按预期返回 10。

虽然如果我这样做:

(eval (let [f (constantly 10)]
`(~f nil)))

它抛出一个异常:

IllegalArgumentException No matching ctor found for 
class clojure.core$constantly$fn__... clojure.lang.Reflector.invokeConstructor

既然两者是等价的,为什么代码总是不起作用?

最佳答案

这个问题有两个答案,要真正明白。

首先,澄清为什么你的 eval在第二种情况下,表单没有给你预期的结果,请注意 f已被分配等于函数 (fn [& _] 10) .这意味着当评估该表单时,将再次评估函数对象——可能不是您想要的。

tl;博士:f当它被绑定(bind)时被评估,当你创建的表单是 eval 时再次被评估(结果不明确) 'd.


一个(匿名函数)有效而另一个失败的原因意味着我们必须查看评估过程的一些内部结构。

当 Clojure 计算对象表达式(如由函数对象形成的表达式)时,它使用以下方法,在 clojure.lang.Compiler$ObjExpr

    public Object eval() {
if(isDeftype())
return null;
try
{
return getCompiledClass().newInstance();
}
catch(Exception e)
{
throw Util.sneakyThrow(e);
}
}

在 REPL 试试这个:

从一个匿名函数开始:

user=> (fn [& _] 10)
#<user$eval141$fn__142 user$eval141$fn__142@2b2a5dd1>

user=> (.getClass *1)
user$eval141$fn__142

user=> (.newInstance *1)
#<user$eval141$fn__142 user$eval141$fn__142@ee7a10e> ; different instance

user=> (*1)
10

请注意 newInstanceClass调用该类的空构造函数——一个不带参数的构造函数。

现在尝试关闭某些值的函数

user=> (let [x 10] #(+ x 1))
#<user$eval151$fn__152 user$eval151$fn__152@3a565388>

user=> (.getClass *1)
user$eval151$fn__152

user=> (.newInstance *1)
InstantiationException user$eval151$fn__152 [...]

由于闭包的上值是在构造时设置的,这种函数类没有空构造函数,并且创建一个没有上下文的新函数类失败。

最后看constantly的出处

user=> (source constantly)
(defn constantly
"Returns a function that takes any number of arguments and returns x."
{:added "1.0"
:static true}
[x] (fn [& args] x))

constantly返回的函数关闭x所以编译器将无法 eval这种功能。

tl;dr(再次):可以用这种方式计算没有上值的函数,并生成相同函数的新实例。不能像这样评估具有上值的函数。

关于clojure - 不断地发挥作用在语法引用中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23573512/

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