请在 2024 年 Clojure 状态调查! 中分享您的想法。

欢迎!请查看 关于页面 获取有关此工作方式的更多信息。

+1
REPL

将 eduction 提供给 repl 将以列表形式打印结果

=> (eduction (map identity) [#'+ 2 3]) (#'clojure.core/+ 2 3)

这不应该评估为 5,因为 eduction 不是一个序列。然而,当我尝试时,我期望得到 eduction 的返回值,但我得到了一个意外的错误,这个错误来自 REPL 中的读取器

=> (eval (eduction (map identity) [#'+ 2 3])) 执行错误 (IllegalArgumentException) 在 user$eval183/<clinit> (REPL:1) 中。找不到与类 clojure.core$map$fn__5880 匹配的构造函数

此错误的堆栈跟踪似乎显示错误发生在读取器中
`
java.lang.ExceptionInInitializerError

at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
at clojure.lang.Compiler$ObjExpr.eval(Compiler.java:5000)
at clojure.lang.Compiler.eval(Compiler.java:7180)
at clojure.lang.Compiler.eval(Compiler.java:7136)
at clojure.core$eval.invokeStatic(core.clj:3202)
at clojure.core$eval.invoke(core.clj:3198)
at user$eval181.invokeStatic(NO_SOURCE_FILE:1)
at user$eval181.invoke(NO_SOURCE_FILE:1)
at clojure.lang.Compiler.eval(Compiler.java:7181)
at clojure.lang.Compiler.eval(Compiler.java:7136)
at clojure.core$eval.invokeStatic(core.clj:3202)
at clojure.core$eval.invoke(core.clj:3198)
at clojure.main$repl$read_eval_print__9110$fn__9113.invoke(main.clj:437)
at clojure.main$repl$read_eval_print__9110.invoke(main.clj:437)
at clojure.main$repl$fn__9119.invoke(main.clj:458)
at clojure.main$repl.invokeStatic(main.clj:458)
at clojure.main$repl_opt.invokeStatic(main.clj:522)
at clojure.main$main.invokeStatic(main.clj:667)
at clojure.main$main.doInvoke(main.clj:616)
at clojure.lang.RestFn.invoke(RestFn.java:397)
at clojure.lang.AFn.applyToHelper(AFn.java:152)
at clojure.lang.RestFn.applyTo(RestFn.java:132)
at clojure.lang.Var.applyTo(Var.java:705)
at clojure.main.main(main.java:40)

由:java.lang.IllegalArgumentException:找不到与类 clojure.core$map$fn__5880 匹配的构造函数

at clojure.lang.Reflector.invokeConstructor(Reflector.java:288)
at clojure.lang.LispReader$EvalReader.invoke(LispReader.java:1317)
at clojure.lang.LispReader$DispatchReader.invoke(LispReader.java:853)
at clojure.lang.LispReader.read(LispReader.java:285)
at clojure.lang.LispReader.read(LispReader.java:216)
at clojure.lang.LispReader.read(LispReader.java:205)
at clojure.lang.RT.readString(RT.java:1879)
at clojure.lang.RT.readString(RT.java:1874)
at user$eval183.<clinit>(NO_SOURCE_FILE:1)
... 27 more

`

源代码在 clojure.lang.LispReader$EvalReader.invoke(LispReader.java:1317) 中表明它正在处理一个以点字符结尾的列表形式。这是意外的

1 答案

+2

通常,并不是每个对象都是可评估的。在评估这样的东西时,会创建一个类,类似于 (fn* [] <eduction-object>)。要创建该类,eduction 对象必须存储在字节码中。在这种情况下,转移函数不能直接存储在字节码中——编译器在这种情况下做出了大胆的尝试,并将一个字符串如 "#=(clojure.core$map$fn__596.)" 进行了 print-dup 到。然后该值试图在 eval 期间读取回类,但该构造函数不可用。这就是你看到的读取错误。

这与从宏返回对象而不是表单时通常会遇到的异常相同,而且你甚至也可以用宏复现这个错误(这是一个常见的宏错误)

(defmacro foo [] (eduction (map identity) [#'+ 2 3]))
(foo)

我不确定我是否期待这能工作——正如你所说,eductions是集合,但不是seqs或lists。

这很有道理,谢谢。我真的很想知道`clojure.core$map$fn__596.`是从哪里来的。
欢迎来到Clojure问答社区,在这里您可以提问并获得Clojure社区成员的答案。
...