代码就是数据,这一公理在人们不得不序列化某些函数之前是成立的。使问题进一步复杂化的是,有时数据是变相的函数。值得注意的是,序列实际上是逻辑列表。如何将无限序列保存到文件中,或者通过网络发送闭包?
如果一个函数是一个不能打开并随时共享的黑盒,那么人们至少可以描述这个黑盒做了什么,而不是不成功地关注它是如何做到这一点的。
(要求';[dvlopt.fdat:as FDAT:refer[?]]';[dvlopt.fdat.plugins.nippy:as fdat.plugins.nippy])';[taoensso.nippy:as nippy])(fdat.plugins.nippy/init)(?(defn hello[x](str";Hello";x)(FDAT/寄存器[hello])(def ba(nippy/Freeze hello))(def hello-2(nippy/thaw ba))(println(hello";world";))。
这段简短的摘录介绍了两个重要的概念:通过使用?谨慎地跟踪";函数是什么?宏,这些信息是我们可以轻松序列化的数据,并维护一个注册表,以便知道在反序列化时如何处理这些知识。
您可以随意克隆此Repo并启动REPL,所有示例都在./dev/user.clj中:
函数是IMeta,这意味着它们可以保存元数据。事实上,我们将要讨论的一切都适用于所有的IMETA。序列是另一个有用的例子,稍后我们甚至会看到所有这些对于任何数据结构都是如何有用的。
那个?宏能够分析生成IMeta的表单,并在其元数据中对其进行注释。
为了从我们的计划中获益,IMETA必须有一个密钥,该密钥在我们讨论注册时具有特殊的意义。宏从Defn中的名称派生密钥。密钥必须始终是合格的。自动提取特别方便。在极少数情况下,我们可能会发现显式提供密钥很有用: