我正在实现一个实际上只是哈希映射包装器的类型
(defn as-pairs [m]
(when-not (empty? m)
(seq (persistent! (reduce (fn [s [k vs]]
(reduce (fn [s v] (conj! s [k v])) s vs)) (transient []) m)))))
(deftype Rel [m]
clojure.lang.Seqable
(seq [this] (as-pairs m))
clojure.lang.ILookup
(valAt [this k] (get m k))
(valAt [this k default] (get m k default))
clojure.lang.IPersistentMap
(assoc [this k v] (Rel. (update m k #(conj (or % #{}) v))))
(assocEx [this k v] (throw (Exception.)))
(without [this k] (Rel. (dissoc m k))))
(defn relation [] (Rel. (hash-map)))
它似乎按预期工作
state-machines.maps> (def r (relation))
#'state-machines.maps/r
state-machines.maps> (type r)
state_machines.maps.Rel
state-machines.maps> r
{} ; interesting that it actually displays a map! -- source of problem?
state-machines.maps> (type (assoc r :foo 1 :foo 2 :bar 1))
state_machines.maps.Rel
state-machines.maps> (get (assoc r :foo 1 :foo 2 :bar 1) :foo)
#{1 2}
state-machines.maps> (seq (assoc r :foo 1 :foo 2 :bar 1))
([:foo 1] [:foo 2] [:bar 1])
state-machines.maps> (assoc r :foo 1 :foo 2 :bar 1)
ClassCastException clojure.lang.PersistentVector cannot be cast to java.util.Map$Entry clojure.core/key (core.clj:1518)
state-machines.maps>
查看堆栈跟踪
1. Unhandled java.lang.ClassCastException
clojure.lang.PersistentVector cannot be cast to java.util.Map$Entry
core.clj: 1518 clojure.core/key
core_print.clj: 212 clojure.core/print-map/fn
core_print.clj: 59 clojure.core/print-sequential
core_print.clj: 208 clojure.core/print-map
core_print.clj: 217 clojure.core/fn
core_print.clj: 217 clojure.core/fn
MultiFn.java: 233 clojure.lang.MultiFn/invoke
pr_values.clj: 35 clojure.tools.nrepl.middleware.pr-values/pr-values/fn/reify
interruptible_eval.clj: 113 clojure.tools.nrepl.middleware.interruptible-eval/evaluate/fn/fn
main.clj: 241 clojure.main/repl/read-eval-print
main.clj: 258 clojure.main/repl/fn
main.clj: 258 clojure.main/repl
main.clj: 174 clojure.main/repl
RestFn.java: 137 clojure.lang.RestFn/applyTo
core.clj: 646 clojure.core/apply
core.clj: 641 clojure.core/apply
regrow.clj: 18 refactor-nrepl.ns.slam.hound.regrow/wrap-clojure-repl/fn
RestFn.java: 1523 clojure.lang.RestFn/invoke
interruptible_eval.clj: 87 clojure.tools.nrepl.middleware.interruptible-eval/evaluate/fn
AFn.java: 152 clojure.lang.AFn/applyToHelper
AFn.java: 144 clojure.lang.AFn/applyTo
core.clj: 646 clojure.core/apply
core.clj: 1881 clojure.core/with-bindings*
core.clj: 1881 clojure.core/with-bindings*
RestFn.java: 425 clojure.lang.RestFn/invoke
interruptible_eval.clj: 85 clojure.tools.nrepl.middleware.interruptible-eval/evaluate
interruptible_eval.clj: 55 clojure.tools.nrepl.middleware.interruptible-eval/evaluate
interruptible_eval.clj: 222 clojure.tools.nrepl.middleware.interruptible-eval/interruptible-eval/fn/fn
interruptible_eval.clj: 190 clojure.tools.nrepl.middleware.interruptible-eval/run-next/fn
AFn.java: 22 clojure.lang.AFn/run
ThreadPoolExecutor.java: 1142 java.util.concurrent.ThreadPoolExecutor/runWorker
ThreadPoolExecutor.java: 617 java.util.concurrent.ThreadPoolExecutor$Worker/run
Thread.java: 745 java.lang.Thread/run
我假设其中一件事正在发生。
core_print.clj: 212 clojure.core/print-map/fn
core_print.clj: 59 clojure.core/print-sequential
core_print.clj: 208 clojure.core/print-map
这是我需要实现的界面吗?
将as-pairs
更新为
(defn as-pairs [m]
(when-not (empty? m)
(seq (persistent! (reduce (fn [s [k vs]]
(reduce (fn [s v] (conj! s (clojure.lang.MapEntry/create k v))) s vs)) (transient []) m)))))
结果是:
state-machines.maps> (assoc (relation) :foo 1 :foo 2 :bar 1)
{:foo 1, :foo 2, :bar 1}
答案 0 :(得分:2)
正如您所怀疑的那样,错误出现在print-map
中,它在其参数上调用seq
,然后在该序列的每个元素上调用key
和val
。正如错误消息所述,这两个函数期望它们的参数符合java.util.Map$Entry
接口,并且Clojure向量不符合该接口。
解决方案是在[k v]
函数中取as-pairs
并将其替换为创建映射条目的表达式;有关详细信息,请参阅this question。