Clojure:函数读取字符串

时间:2013-06-23 18:27:54

标签: clojure

是否可以使用具有功能值的阅读器,例如:

  

(read-string(pr-str +))

     

RuntimeException不可读的表单clojure.lang.Util.runtimeException   (Util.java:219)

2 个答案:

答案 0 :(得分:3)

您可能已经知道(pr-str +)的输出无效,读者可以解析的Clojure代码:"#<core$_PLUS_ clojure.core$_PLUS_@ff4805>"。使用函数prprnprintln等时函数值的输出有意地包含在发送到UnreadableReader#<阅读器宏周围,throws您看到的例外情况。

对于您提供的示例,您可以使用适用于基本序列化的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内部。

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

希望它有所帮助,

答案 1 :(得分:0)

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

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

但也许您只需要将字符串转换回符号,在这种情况下(符号名称)功能就足够了。