2024 年 Clojure 状态调查! 中分享您的想法。

欢迎!有关本网站的更多信息,请参阅 关于 页面。

0
Clojure
在折叠函数中遇到了一个令人困惑的异常。以下为 REPL 转录:


nREPL 服务器在主机 127.0.0.1 的端口 57818 上启动 - nrepl://127.0.0.1:57818
REPL-y 0.3.5,nREPL 0.2.6
Clojure 1.7.0-alpha5
Java HotSpot(TM) 64 位数组服务器 VM 1.7.0_76-b13
    文档: (doc 函数名称)
           使用 (find-doc "部分名称") 查找文档
  源代码: (source 函数名称)
 Java 文档: (javadoc java 对象或类名称)
    退出: Control+D 或 (exit) 或 (quit)
 结果: 存储在 *1,*2,*3 变量中,异常存储在 *e 变量中

user=> (use 'foldtest.core)
nil
user=> (source leafs)
(defn leafs [xs]
  (->> (r/mapcat (fn [k v]
                   (if (map? v)
                     leafs v
                     [[k v]]) xs)
       r/foldcat)))
nil
user=> (leafs (hash-map :a (hash-map :b 1 :c 2)))

ClassCastException clojure.lang.PersistentHashMap$1 无法转换为 clojure.lang.IFn  clojure.core.reducers/fjinvoke (reducers.clj:48)
user=> (pst)
ClassCastException clojure.lang.PersistentHashMap$1 无法转换为 clojure.lang.IFn
    clojure.core.reducers/fjinvoke (reducers.clj:48)
    clojure.lang.PersistentHashMap.fold (PersistentHashMap.java:207)
    clojure.core.reducers/eval1347/fn--1348 (reducers.clj:367)
    clojure.core.reducers/eval1220/fn--1221/G--1211--1232 (reducers.clj:81)
    clojure.core.reducers/folder/reify--1247 (reducers.clj:130)
    clojure.core.reducers/fold (reducers.clj:98)
    clojure.core.reducers/fold (reducers.clj:96)
    clojure.core.reducers/foldcat (reducers.clj:318)
    foldtest.core/leafs (core.clj:5)
    foldtest.core/leafs/fn--1367 (core.clj:7)
    clojure.core.reducers/mapcat/fn--1277/fn--1280 (reducers.clj:185)
    clojure.lang.PersistentHashMap$NodeSeq.kvreduce (PersistentHashMap.java:1127)
nil
user=>


请注意,它 *必须* 是嵌入在哈希表中的哈希表。其他组合的数组和哈希表似乎都很正常


user=> (leafs (array-map :a (hash-map :b 1 :c 2)))
[[ :c 2] [ :b 1]]
user=> (leafs (hash-map :a (array-map :b 1 :c 2)))
[[ :b 1] [ :c 2]]
user=> (leafs (hash-map :a (hash-map :b 1 :c 2)))

ClassCastException clojure.lang.PersistentHashMap$1 无法转换为 clojure.lang.IFn  clojure.core.reducers/fjinvoke (reducers.clj:48)
user=> (leafs (array-map :a (array-map :b 1 :c 2)))
[[ :b 1] [ :c 2]]
user=>


可能相关: CLJCLR-63

由于这种不一致性(我不确定这是一个错误),我花了好长时间才发现这一点


user=> (def a {:a 1})
#'user/a
user=> (type a)
clojure.lang.PersistentHashMap
user=> (let [a {:a 1}] (type a))
clojure.lang.PersistentArrayMap
user=> (type {:a 1})
clojure.lang.PersistentArrayMap
user=>


(我曾在定义中放入了测试输入,但使用该定义的变量总是失败,但文本字面量总是可以工作!)

2 个答案

0
by

评论由:favila 制作

我在 CLJ 1.8 和 master (1.9)以及 Java 8 上确认了这个问题仍然存在。

我能够诊断出问题的原因。问题在于 PHMs 的 {{.fold}} 方法为 {{fjinvoke}} 创建了一个 {{Callable}}(而不是一个 {{IFn}}),但 {{fjinvoke}} 会像一个正常的 clojure 函数({{IFn .invoke}})一样调用它的参数。这是唯一提供纯 {{Callable}} 给 {{fjinvoke}} 的 Clojure-core foldable 数据结构。通常这个问题不会出现,因为任务不是在运行的任务中调用的,而是在一个已经运行的任务中执行的嵌套折叠会在 {{fjinvoke}} 中的 {{(f)}} 行触达并崩溃。

因为 Clojure 函数也是 {{Callable}},所以我的修复方案是将 {{fjinvoke}} 的契约收紧,接收一个 {{Callable}} 并用 {{.call}} 调用参数而不是调用它。另一种修复方案是将 PHM 的 {{.fold}} 改为创建一些更具 Clojure 函数风格的东西(既可调用也可调用)。

0
by
参考:https://clojure.atlassian.net/browse/CLJ-1662(由 favila 报告)
...