2024 Clojure调查中分享您的想法!

欢迎!请参阅关于页面以获得更多关于如何使用本网站的信息。

+1
REPL

向REPL提供eduction将按列表格式打印结果

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

这不应该求值为5,因为eduction不是一个序列。然而,当我尝试时,我期望得到eduction的返回值,但出乎意料地我在REPL的读取器中得到一个错误

=> (eval (eduction (map identity) [#'+ 2 3])) 执行错误 (IllegalArgumentException) 在 user$eval183/ (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)

原因:找不到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对象存储在字节码中。在这种情况下,transducer函数不能直接存储在字节码中——在这种情况下,编译器冒着极大的风险尝试将print-dup操作应用于字符串“#=(clojure.core$map$fn__596.)”,然后试图在eval执行期间重新读取该值,但由于类构造器不可用,所以出现了读取错误。这就是你所看到的读取错误。

这与你从宏中返回对象而不是形式的错误相同,实际上你还可以用宏来复现这个错误(这是一个常见的宏错误)

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

我不知道是否应该期望这一点能够工作——正如你所说的,eduction是集合,但不是序列或列表。

by
这很有道理,谢谢。我真的很想了解`clojure.core$map$fn__596.`的来源。
...