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

欢迎!请查看关于页面了解有关此功能的一些更多信息。

+1投票
ClojureScript

我正在尝试将datascript数据库序列化为JSON,以便在文件系统中进行存储。
我的数据库中包含一些函数。由于一些不重要的原因,目前需要将它们与其他应用会话信息一起存储在数据库中。但当我调用Transit时,出现“无法写入Function”的异常。

我查看了代码,它仅仅试图处理数据结构,如map和vector等。但没有为函数提供处理器。所以我知道出错的原因,但我的问题是为什么没有将功能也序列化呢?

是不是太新颖了?

谢谢

1 答案

+2投票
by

Clojure中,函数是不透明的对象,您不能从对象中恢复源。

by
defn 没有将源码作为元数据添加,这是 clojure.repl/source 工作方式的一部分吗?
by
不是的,defn 存储文件和行号在 var 的 meta (不是函数本身)中,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。

总的来说,你可能需要用不同的方式来处理这个问题。但是,如果这只是为了好玩,上述方法是很有趣的。
...