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_Records - Fatal编程技术网

从Clojure记录返回普通映射

从Clojure记录返回普通映射,clojure,records,Clojure,Records,我有一个记录: (defrecord Point [x y]) (def p (Point. 1 2)) 现在我只想从记录中提取地图。这些方法可以完成工作。这些是好方法吗?有更好的方法吗 (into {} (concat p)) (into {} (map identity p)) (apply hash-map (apply concat p)) 我希望有一种更干净的方法,也许是内置于记录的概念中。建议在注释中使用更简单的(into{}p)。谢谢 下面是一个更一般的代码片段;它适用于递归记

我有一个记录:

(defrecord Point [x y])
(def p (Point. 1 2))
现在我只想从记录中提取地图。这些方法可以完成工作。这些是好方法吗?有更好的方法吗

(into {} (concat p))
(into {} (map identity p))
(apply hash-map (apply concat p))
我希望有一种更干净的方法,也许是内置于记录的概念中。

建议在注释中使用更简单的
(into{}p)
。谢谢

下面是一个更一般的代码片段;它适用于递归记录:

(记录事物[ab])
(定义t1(事物1.2))
(def t2(Thing.3.4))
(def t3(Thing.t1 t2))
(defn记录->地图
[纪录]
(让[f#)(如果(记录?%)(记录->映射%)
ks(钥匙记录)
vs(地图f(VAL记录))]
(zipmap ks vs)))
(记录->地图t3)
; {:b{:b 4,:a 3},:a{:b 2,:a 1}

我还编写了一个通用函数,用于将(大多数)任意Clojure数据结构的记录转换为映射:

(defn derecordize
  "Returns a data structure equal (using clojure.core/=) to the
  original value with all records converted to plain maps."
  [v]
  (cond
    (record? v) (derecordize (into {} v))
    (list? v) (map derecordize v)
    (vector? v) (mapv derecordize v)
    (set? v) (set (map derecordize v))
    (map? v) (zipmap (map derecordize (keys v)) (map derecordize (vals v)))
    :else v))
我知道这很不寻常。当您需要导出没有记录的数据结构时,这非常有用。

记录是映射

因此,通常不需要将它们强制为
apResistentMap
类型。但是,如果需要,可以将
转换为

(into {} t1) ;=> {:a 1, :b 2}
如果要遍历任意数据结构(包括嵌套记录),进行此转换,请使用
walk

(def t2 (Thing. 3 4))
(def t3 (Thing. t1 t2))
(def coll (list t1 [t2 {:foo t3}]))

(clojure.walk/postwalk #(if (record? %) (into {} %) %) coll)
;=> ({:a 1, :b 2} [{:a 3, :b 4} {:foo {:a {:a 1, :b 2}, :b {:a 3, :b 4}}}])

你为什么要这么做?记录已经是持久映射的实现了。是的,我知道记录可以完成映射可以完成的所有事情。我还是想做。想法?这是更好的答案(轻推)!我只是浏览了一下,但没有找到内置的Java方法。
(clojure.walk/postwark#(if(record?%)(into{}%)%)t3)
a.韦伯:这是一个更好的答案。想发布吗?这就是
walk
所做的。它了解任意数据结构、列表、向量、地图、集合。。。包括记录。此外,您基本上不应该调用
list?
-您的意思是在这种情况下使用
seq?
(与大多数情况一样)。例如,
(对于[x(范围5)](MyRecord.x))
,您建议的解决方案不起作用。谢谢!我的用例是“映射”数据结构中的记录,以紧凑的方式序列化,使测试更具可读性。(Clojure的默认记录序列化非常详细,特别是当您有类型提示并使用
print dup
)@DavidJames
((get-method-print-method-java.util.Map)(Thing.1 2)*out*);=>{:A1,:B2}
(def t2 (Thing. 3 4))
(def t3 (Thing. t1 t2))
(def coll (list t1 [t2 {:foo t3}]))

(clojure.walk/postwalk #(if (record? %) (into {} %) %) coll)
;=> ({:a 1, :b 2} [{:a 3, :b 4} {:foo {:a {:a 1, :b 2}, :b {:a 3, :b 4}}}])