(postwalk #(do (println "visiting:" %)
(if (vector? %)
(seq %)
%))
[:title {:bu "hu"}])
我的期望(没有printlns):(:title {:bu "hu"})
我得到了什么:
visiting: :title
visiting: :bu
visiting: hu
visiting: [:bu hu]
Stack trace of root exception is empty; this is likely due to a JVM optimization
that can be disabled with -XX:-OmitStackTraceInFastThrow.
java.lang.ClassCastException:
为什么要访问[:bu hu]
而不是{:bu hu}
?它似乎与嵌套的矢量很好,但扔了一张地图,jvm对我生气,呕吐难以理解的淫秽。
答案 0 :(得分:4)
我得到了更好的堆栈跟踪:
visiting: :title
visiting: :bu
visiting: hu
visiting: [:bu hu]
ClassCastException clojure.lang.Keyword cannot be cast to java.util.Map$Entry clojure.lang.ATransientMap.conj (ATransientMap.java:44)
[:bu hu]
不是地图,而是地图中的第一个MapEntry
。不幸的是,它实际上并不是clojure.lang.MapEntry
的实例。在您传递到walk
的函数被应用之前,postwalk
会将其变为向量(postwalk
在内部调用walk
。即使在reading the code之后我仍然难以相信。
我不确定这是最好的方法。但我认为至少要知道为什么会发生这种情况对你有帮助。
答案 1 :(得分:1)
[:bu" hu"]是一个clojure.lang.MapEntry,postwalk将访问地图中的每个条目。可悲的是,clojure.walk / postwalk将MapEntry作为clojure.lang.PeristentVector传递,因此无法在postwalk中可靠地区分条目和向量。我想你需要使用你自己的步行实现。