我想在Clojure中将元数据添加到字节数组中。由于这是不允许的,我想尝试的一个选项是可以工作的最简单的对象包装器。
以下是with-meta的源代码。
这让我开始关注Clojure.lang.IObj
。我还没找到我想要的东西。
答案 0 :(得分:5)
以下是如何创建支持元数据的deftype
。
(import '(java.io Writer))
(deftype Box [value _meta]
clojure.lang.IObj
(meta [_] _meta)
(withMeta [_ m] (Box. value m))
clojure.lang.IDeref
(deref [_] value)
Object
(toString [this]
(str (.getName (class this))
": "
(pr-str value))))
(defmethod print-method Box [o, ^Writer w]
(.write w "#<")
(.write w (.getName (class o)))
(.write w ": ")
(.write w (-> o deref pr-str))
(.write w ">"))
(defn box
([value] (box value nil))
([value meta] (Box. value meta)))
以下是一些示例用法:
user> (def boxed (box (->> (range 5)
(map byte)
(byte-array))
{:stuff :foo}))
#<Var@1acd39b: #<Box@c50aa1: #>>
user> @boxed
[0, 1, 2, 3, 4]
user> (meta boxed)
{:stuff :foo}
user> (meta (with-meta boxed {:stuff :bar}))
{:stuff :bar}
这是我可以想到的将元数据放在字节数组上的最简单方法(reify
不能与clojure.lang.IObj
一起使用,并且记录包含更多不相关的功能。)
另一个选项(可能更简单,取决于上下文)将字节数组存储在地图中,元数据可以与其一起或作为实际元数据。
答案 1 :(得分:1)
在与#clojure IRC的一些人讨论之后,我写了一个简单的Java类MetaBox
,它实现了clojure.lang.IObj
。您可以在Clojure中使用metabox/box
和metabox/val
以及meta
和with-meta
等常用元数据功能轻松使用此功能。
; [metabox "0.1.0"]
(require '[metabox.core :refer (box val)])
(def critical-density (box 0.692 {:uncertainty 0.01}))
(val critical-density) ; 0.692
(meta critical-density) ; {:uncertainty 0.01}
您可以在clj-metabox找到源代码和README。
更新:感谢一些讨论和建议(见下文),自version 0.2.0起,API使用deref
代替val
:
; [metabox "0.2.0"]
(require '[metabox.core :refer (box)])
(def critical-density (box 0.692 {:uncertainty 0.01}))
@critical-density ; 0.692
(meta critical-density) ; {:uncertainty 0.01}