Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
可以接受原语和元数据的最简单的Clojure对象?_Clojure_Metadata - Fatal编程技术网

可以接受原语和元数据的最简单的Clojure对象?

可以接受原语和元数据的最简单的Clojure对象?,clojure,metadata,Clojure,Metadata,我想在Clojure中将元数据添加到字节数组中。因为这是不允许的,所以我想尝试的一个选项是最简单的对象包装器 下面是的源代码 这让我开始看Clojure.lang.IObj。我还没有找到我想要的。以下是如何创建支持元数据的 (import '(java.io Writer)) (deftype Box [value _meta] clojure.lang.IObj (meta [_] _meta) (withMeta [_ m] (Box. value m)) clojure.

我想在Clojure中将元数据添加到字节数组中。因为这是不允许的,所以我想尝试的一个选项是最简单的对象包装器

下面是的源代码


这让我开始看
Clojure.lang.IObj
。我还没有找到我想要的。

以下是如何创建支持元数据的

(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)))
(导入(java.io编写器))
(定义类型框[值]
clojure.lang.IObj
(元
(带meta[m](框值m))
clojure.lang.IDeref
(deref[u]值)
对象
(toString[这个]
(str(.getName(该类))
": "
(pr str值)
(定义方法打印方法框[o,^w]
(.写w“#”))
(除霜盒
([值](框值为零))
([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}
user>(def盒装(框(->>(范围5))
(映射字节)
(字节数组)
{:stuff:foo})
#
用户>@已装箱
[0, 1, 2, 3, 4]
用户>(元框)
{:stuff:foo}
用户>(元(带有元框{:stuff:bar}))
{:stuff:bar}
这是我能想到的将元数据放在字节数组上的最简单方法(
reify
不适用于
clojure.lang.IObj
并且记录包含更多不相关的功能)


另一种选择(可能更简单,具体取决于上下文)是将字节数组存储在映射中,元数据要么放在映射旁边,要么作为实际元数据。

在与一些人讨论了#clojure IRC之后,我编写了一个简单的Java类,
MetaBox
,它实现了
clojure.lang.IObj
。您可以在Clojure中使用
metabox/box
metabox/val
以及常见的元数据功能,如
meta
with meta
,轻松使用此功能

(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)))
; [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}

您可以在上找到源代码和自述文件

更新:由于一些讨论和建议(见下文),截至,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}

你看过吗?@DaoWen是的,我看过。我正在树立一个榜样;如果它有任何承诺,我将与您分享。您是出于什么考虑而选择此而不是
deftype
?顺便说一句,由于没有前缀
val
会对
clojure.core/val
造成阴影,因此可能值得使用其他东西(
value
val of
可能?),实际上,
clojure.lang.IDeref
可能是一种公开该值的好方法。我更新了我的示例代码,将其包括在内(并采用了术语
box
)。jbm:我们刚刚讨论了IRC上的引用类型。这是一个有趣的想法,
deref
/
@
语法干净而诱人。然而,对于我的特定用例,引用类型有太多的细节。Clojure让他们管理状态和身份。我只需要不变性;我不需要也不希望装箱的值可以按照ref、agent或agent提供的方式进行设置或更改。我不想像延迟、未来或承诺那样延迟或转移计算。Deftype不创建引用类型——它本质上生成一个Java类(有关详细信息,请参阅)。代理、期货等与我的建议无关,只是它们碰巧通过
IDeref
公开了各种功能。此外,虽然deftypes可以有可变字段(正如Java类可以),但默认情况下它们没有(我的示例也没有)。基本上,我认为你可能误解了“参考类型:)你所说的“参考类型”是什么意思?当然,对于“引用类型”的某些定义,实现
IDeref
会使类型成为“引用类型”,但仅仅使用不同的函数去引用并不一定会使类型减少“引用类型”。是的,
deftype
比手工编写Java类更紧凑。一些评论。Clojure将空元数据存储为
nil
,而不是
{}
。另外,实现
toString
也不错。@DavidJames,我添加了简单的
toString
print方法
实现,并将默认元数据从
{}
更改为
nil