我想在Clojure中为字节数组添加元数据,由于不允许这样做,所以我想尝试的一个选项是最简单的可行的对象包装器。
下面是“with-meta”的源代码,您可以访问此处。
这使我开始查看
下面是“with-meta”的源代码,您可以访问此处。
这使我开始查看
Clojure.lang.IObj
,但我还没有找到我想要的内容。以下是如何创建一个支持元数据的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
一起使用,而记录包括更多无关功能)。deftype
比手写 Java 类更加简洁。还有一点需要注意,Clojure 会将空元数据存储为 nil
,而不是 {}
。另外,实现 toString
方法也是很不错的选择。 - David J.toString
和print-method
实现,并将默认元数据从{}
更改为nil
。 - jbm在 #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}
更新: 感谢一些讨论和建议(见下文),从版本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}
deftype
的考虑是什么?顺便说一下,由于没有前缀 val
会遮盖 clojure.core/val
,因此使用其他名称(例如 value
或 val-of
)可能更值得一试。 - jbmclojure.lang.IDeref
可能是公开值的好方法。我更新了我的示例代码以包括它(并采用了术语 box
)。 - jbmclojure.lang.IDeref
的。 - David J.Box
一样似乎并不更像引用,但我同意取消引用会应用一个引用的观点。(我开始考虑 IDeref
的原因是,将值装箱会添加一个 大致 类似于 Var
的间接级别)。在通俗的英语中,Box
是一个值和其元数据的引用,尽管它没有 Clojure 引用类型的状态/身份特征。(现在我要停止对您的问题进行骚扰并去睡觉 :)) - jbmIDeref
使得某种定义下的类型成为“引用类型”,但仅仅使用不同的解引用函数并不能使类型变得不那么像“引用类型”。 - Nathan Davis
clojure.lang.Obj
了吗? - DaoWen