2

有没有办法将阅读器与函数值一起使用,例如:

(读取字符串(pr-str +))

RuntimeException 不可读的形式 clojure.lang.Util.runtimeException (Util.java:219)

?

4

2 回答 2

3

您可能已经知道输出(pr-str +)不是读者可以解析的有效 Clojure 代码:"#<core$_PLUS_ clojure.core$_PLUS_@ff4805>". 使用函数时,函数值的输出prprnprintln,故意包裹在#<调度到的读取器宏中UnreadableReader,这会引发您看到的异常。

对于您提供的示例,您可以使用print-dup适用于基本序列化的函数:

(defn string-fn [f]
  (let [w    (java.io.StringWriter.)]
    (print-dup f w)
    (str w)))

(let [plus (read-string (string-fn +))]
  (plus 1 2))

为函数完成的序列化+实际上是生成对类的构造函数的调用:

#=(clojure.core$_PLUS_. )

当然,这只适用于已经在读取字符串的 Clojure 环境中编译的类。如果你序列化了一个匿名函数,将它保存到一个文件然后读回它,那么在运行一个新的 REPL 会话时,它很可能无法工作,因为每个匿名函数的类名不同并且取决于 Clojure 内部。

对于任意函数,事情变得更加复杂。共享源代码甚至可能还不够,该函数可能依赖于使用仅存在于源环境中的任意数量的其他函数或变量。如果这是您正在考虑做的事情,也许考虑其他方法来解决您尝试解决的问题,将消除序列化任意函数值的需要。

希望能帮助到你,

于 2013-06-23T19:52:33.880 回答
0

如果您只需要名称,您可以发送带有 (name '+) 的符号。

但一般来说,使用 clojure read 是一个坏主意,如果你想读回它,因为 clojure 的 reader 可能会在这个过程中执行一些代码。也许看看 edn 阅读器:clojure.edn/read-string

但也许您只需要将字符串转换回符号,在这种情况下, (symbol name) 函数就足够了。

于 2013-06-23T20:17:49.917 回答