问题
I want to add metadata to a byte array in Clojure. Since this is not allowed, one option I want to try is the simplest object wrapper that could work.
Here is the source code for with-meta.
That made me start looking at Clojure.lang.IObj
. I haven't found what I want yet.
回答1:
Here's how you can create a deftype that supports metadata.
(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)))
And here's some example usage:
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}
This is the simplest way I can think of to put metadata on a byte array (reify
doesn't work with clojure.lang.IObj
and records include more unrelated functionality).
Another option (and perhaps simpler depending on the context) would be to store the byte array in a map, with the metadata either right alongside it or as actual metadata.
回答2:
After discussing with some people on #clojure IRC, I wrote a simple Java class, MetaBox
, that implements clojure.lang.IObj
. You can use this easily in Clojure with metabox/box
and metabox/val
as well as the usual metadata functions such as meta
and 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}
You can find the source code and README over at clj-metabox.
UPDATE: Thanks to a few discussions and suggestion (see below), as of version 0.2.0, the API uses deref
instead of 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}
来源:https://stackoverflow.com/questions/20724219/simplest-possible-clojure-object-that-can-accept-a-primitive-and-metadata