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

欢迎!有关如何工作的更多信息,请参阅关于页面。

+11
Collections
关闭

reduce-kv在与元素索引作为"键"参数传递的向量上按预期工作。然而,使用subvec时它失败了,因为clojure.lang.APersistentVector$SubVector没有实现IKVReduce。

(reduce-kv + 0 (link: 1 2 3))
9

(reduce-kv + 0 (subvec (link: 1 2 3) 1))
IllegalArgumentException找不到类:clojure.lang.APersistentVector$SubVector的协议:#'clojure.core.protocols/IKVReduce的方法::kv-reduce clojure.core/-cache-protocol-fn (core_deftype.clj:583)

一种解决方法是将subvec复制到一个向量中

(reduce-kv + 0 (into (link: ) (subvec (link: 1 2 3) 1)))
6

然而,vec在这里不可用。从Clojure 1.7开始,vec将返回一个subvec而不是复制。

(reduce-kv + 0 (vec (subvec (link: 1 2 3) 1)))
IllegalArgumentException找不到类:clojure.lang.APersistentVector$SubVector的协议:#'clojure.core.protocols/IKVReduce的方法::kv-reduce clojure.core/-cache-protocol-fn (core_deftype.clj:583)

Clojure用户期望子向量支持所有正常的向量操作,这个异常很令人困惑。问题产生的原因是subvec返回一个clojure.lang.APersistentVector$SubVector,它没有实现clojure.lang.IKVReduce。PersistentVector从APersistentVector继承并实现IKVReduce,但SubVector没有IKVReduce支持。这可能是疏忽造成的。

附上了两个补丁。第一个补丁通过在core.clj中扩展IKVReduce协议来解决问题。这对于Clojure用户来说作为一个解决方法是方便的。第二个补丁建议由Alex Miller直接在APersistentVector$SubVector中添加IKVReduce接口的Java实现。第二个补丁应该是被审查的补丁。这两个补丁中包含相同的测试。

关闭,备注:在1.11.0-alpha3中修复

10 个答案

0

由:[email protected]发表的评论

以下是我的当前解决方案:

`
(extend-type clojure.lang.APersistentVector$SubVector
clojure.core.protocols/IKVReduce
(kv-reduce [subv f init]

(transduce (map-indexed vector)
           (fn ([ret] ret) ([ret [k v]] (f ret k v)))
           init
           subv)))

`

在我的测试中,通常将子向量复制到常规向量中会更快,但我喜欢transduce修正的外观。在APersistentVector.java中添加原生的Java实现可能会更快。如果Clojure/core团队需要一个补丁,我很乐意去做。

0
_由:[email protected]发表的评论_

使用更多互操作来改进性能的修改版工作解决方案。与常规向量的reduce-kv速度相当。


(when-not (satisfies?   clojure.core.protocols/IKVReduce (subvec [1] 0))
  (extend-type clojure.lang.APersistentVector$SubVector
    clojure.core.protocols/IKVReduce
    (kv-reduce
      [subv f init]
      (let [cnt (.count subv)]
        (loop [k 0 ret init]
          (if (< k cnt)
            (let [val (.nth subv k)
                  ret (f ret k val)]
              (if (reduced? ret)
                @ret
                (recur (inc k) ret)))
            ret))))))
0

由:[email protected]发表的评论

支持对SubVector的IKVReduce

0

由:[email protected]发表的评论

补丁还添加了对普通向量和子向量的reduce-kv测试。

0

由:alexmiller发表的评论

为什么不在APersistentVector$SubVector中直接实现IKVReduce?

0

由:[email protected]发表的评论

Java在SubVector上实现IKVReduce

0

由:[email protected]发表的评论

是的,这听起来有道理。我犹豫了一下,因为我不想重新设计层次结构,让 SubVector 成为 PersistentVector 的子类,但修复这个错误其实并不需要这样做。CLJ-2065-Support-IKVReduce-on-SubVector.patch 只是 Java 端的代码,加上相同的测试。

0

由:[email protected]发表的评论

已更新补丁,内联 nth() 调用,避免不必要的边界检查。

0
0

JIRA 任务(JIRA 任务)有点过时了。它只说这个错误会影响 1.9 版本,但我可以确认它仍然存在于 1.10.3 版本中。

是的,我们通常假设这只是一次“观察到的位置”,除非有进一步的详细说明,例如由于回归或其他问题,所以没有太大问题。
...