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

欢迎!请参阅 关于 页面以获取更多关于此如何运作的信息。

+1 投票
ClojureScript

我正在尝试将 datascript 数据库序列化为 JSON 以存储在文件系统上。
我数据库中的一些数据包含了函数。由于一些无关紧要的原因,我需要现在将它们与应用程序的其他会话信息一起存储在数据库中。但我遇到了一个异常,Transit 显示 "不能写入 Function"。

我查看了代码,它只是尝试处理数据结构 -- 映射、向量等。但没有处理函数的处理程序。所以我知道为什么我遇到了错误,但是我的问题的要点是为什么没有实现序列化函数的功能?

这仅仅是一个过于新颖的想法吗?

谢谢

1 答案

+2 投票

Clojure 中的函数是透明对象,并且你无法从对象中恢复源代码。

defn 没有将源代码添加到元信息中,这是 clojure.repl/source 的工作方式吗?
by
不是,defn 将文件名和行号存储在 var 元信息中(不是函数本身),source 使用这些信息来寻找源代码形式,并从源文件中读取它。这假设了 a)存在一个可变变量,b)定义此变量的源文件是可访问的。实际上,这些可能都不成立(这就是 source 无法工作的情况)。
by
听起来我触碰到了 Clojure(script) 的工作原理的本质,这不仅仅是实现它的时间问题。感谢 @alexmiller 和 @Didier A 的回答。我现在更明白了。
by
我明白了。虽然这可能听起来相当棘手,但理论上,你可以修改 defn 和 fn,只为你要序列化的函数存储函数源代码和环境。

大致就像这些尝试所做的那样

https://github.com/sorenmacbeth/serializable-fn
https://github.com/technomancy/serializable-fn

但是,这也可能有一些限制。例如,它们不会递归地序列化它们自己调用的函数和宏。所以当你反序列化它们时,你应该确保在一个具有它们所需所有依赖的命名空间中这样做。

另外,我不确定你能否在 ClojureScript 中这样做。在反序列化时,你将无法使用 eval。

总的来说,你可能需要以不同的方式处理这个问题。但如果是出于娱乐,上述方法很有趣。
...