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

欢迎!请参阅 关于 页面以获取更多有关该功能的信息。

0
core.rrb-vector
我遇到了一些奇怪的行为,但我找不到一个小型失败的用例。


(defn quicksort [v]
  (if (<= (count v) 1)
    v
    (let [[x & xs] v]
      (rrb/catvec (quicksort (filterv #(<= % x) xs))
                  [x]
                  (quicksort (filterv #(> % x) xs))))))


我们可以使用 test.check 来检查这个实现。


(defn ascending? [coll]
  (every? (fn [[a b]] (<= a b))
          (partition 2 1 coll)))

(def property
  (prop/for-all [v (gen/vector gen/int)]
    (let [s (quicksort v)]
      (and (= (count v) (count s))
          (ascending? s)))))

(tc/quick-check 10000 property)

;; => {:result true, :num-tests 10000, :seed 1440948212354}


(我已经将检查次数增加到 1e6,但 test.check 无法找到失败的用例)

尽管如此,对于某种原因,我为附带的 1193 个元素的向量得到了 "ClassCastException: clojure.lang.PersistentVector$Node cannot be cast to [I"。

{}
(quicksort (read-string (slurp "failing-1193.edn")))
{}

5 个答案

0
_由 jonase_ 发表的评论

表达式


(quicksort (shuffle (range 1e6)))


1. 成功 (~20%)
2. 抛出 ArrayIndexOutOfBoundsException (~20%)


#error {
 :cause "33"
 :via
 [{:type java.lang.ArrayIndexOutOfBoundsException
   :message "33"
   :at [clojure.core.rrb_vector.rrbt.Vector$fn__3827 invoke "rrbt.clj" 621]}]
 :trace
 [[clojure.core.rrb_vector.rrbt.Vector$fn__3827 invoke "rrbt.clj" 621]
  [clojure.core.rrb_vector.rrbt.Vector arrayFor "rrbt.clj" 620]
  [clojure.core.rrb_vector.rrbt.VecSeq chunkedNext "rrbt.clj" 111]
  [clojure.core.rrb_vector.rrbt.VecSeq next "rrbt.clj" 74]
  [clojure.lang.RT next "RT.java" 674]
  [clojure.core$next__4112 invoke "core.clj" 64]
  [clojure.core$nthnext invoke "core.clj" 3038]
  [clojure.core$print_sequential invoke "core_print.clj" 49]
  [clojure.core$fn__5859 invoke "core_print.clj" 206]
  [clojure.lang.MultiFn invoke "MultiFn.java" 233]
  [clojure.tools.nrepl.middleware.pr_values$pr_values$fn$reify__600 send "pr_values.clj" 35]
  [sun.reflect.GeneratedMethodAccessor13 invoke nil -1]
  [sun.reflect.DelegatingMethodAccessorImpl invoke "DelegatingMethodAccessorImpl.java" 43]
  [java.lang.reflect.Method invoke "Method.java" 606]
  [clojure.lang.Reflector invokeMatchingMethod "Reflector.java" 93]
  [clojure.lang.Reflector invokeInstanceMethod "Reflector.java" 28]
  [clojure.tools.nrepl.middleware.load_file$wrap_load_file$fn$reify__787 send "load_file.clj" 93]
  [clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__623$fn__634 invoke "interruptible_eval.clj" 82]
  [clojure.main$repl$read_eval_print__7099 invoke "main.clj" 241]
  [clojure.main$repl$fn__7108 invoke "main.clj" 258]
  [clojure.main$repl doInvoke "main.clj" 258]
  [clojure.lang.RestFn invoke "RestFn.java" 1523]
  [clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__623 invoke "interruptible_eval.clj" 58]
  [clojure.lang.AFn applyToHelper "AFn.java" 152]
  [clojure.lang.AFn applyTo "AFn.java" 144]
  [clojure.core$apply invoke "core.clj" 630]
  [clojure.core$with_bindings_STAR_ doInvoke "core.clj" 1868]
  [clojure.lang.RestFn invoke "RestFn.java" 425]
  [clojure.tools.nrepl.middleware.interruptible_eval$evaluate invoke "interruptible_eval.clj" 56]
  [clojure.tools.nrepl.middleware.interruptible_eval$interruptible_eval$fn__665$fn__668 invoke "interruptible_eval.clj" 191]
  [clojure.tools.nrepl.middleware.interruptible_eval$run_next$fn__660 invoke "interruptible_eval.clj" 159]
  [clojure.lang.AFn run "AFn.java" 22]
  [java.util.concurrent.ThreadPoolExecutor runWorker "ThreadPoolExecutor.java" 1145]
  [java.util.concurrent.ThreadPoolExecutor$Worker run "ThreadPoolExecutor.java" 615]
  [java.lang.Thread run "Thread.java" 745]]}


3. 抛出上述提到的 ClassCastException (~60%)


#error {
 :cause "clojure.lang.PersistentVector$Node 不能转换为 [I"
 :via
 [{:type clojure.lang.Compiler$CompilerException
   :message "java.lang.ClassCastException: clojure.lang.PersistentVector$Node cannot be cast to [I, compiling:(/Users/jonasenlund/dev/clojure/the-other-datastructures/src/the_other_datastructures/rrb.clj:221:1)"
   :at [clojure.lang.Compiler load "Compiler.java" 7239]}
  {:type java.lang.ClassCastException
   :message "clojure.lang.PersistentVector$Node cannot be cast to [I"
   :at [clojure.lang.Numbers ints "Numbers.java" 1396]}]
 :trace
 [[clojure.lang.Numbers ints "Numbers.java" 1396]
  [clojure.core.rrb_vector.nodes$fold_tail invoke "nodes.clj" 265]
  [clojure.core.rrb_vector.nodes$fold_tail invoke "nodes.clj" 268]
  [clojure.core.rrb_vector.rrbt$splice_rrbts invoke "rrbt.clj" 1357]
  [clojure.core.rrb_vector.rrbt.Vector splicev "rrbt.clj" 928]
  [clojure.core.rrb_vector$catvec invoke "rrb_vector.clj" 54]
  [the_other_datastructures.rrb$eval4682$quicksort__4683 invoke "rrb.clj" 217]
  [the_other_datastructures.rrb$eval4682$quicksort__4683 invoke "rrb.clj" 217]
  [the_other_datastructures.rrb$eval4682$quicksort__4683 invoke "rrb.clj" 217]
  [the_other_datastructures.rrb$eval4682$quicksort__4683 invoke "rrb.clj" 219]
  [the_other_datastructures.rrb$eval4682$quicksort__4683 invoke "rrb.clj" 217]
  [the_other_datastructures.rrb$eval4682$quicksort__4683 invoke "rrb.clj" 219]
  [the_other_datastructures.rrb$eval4682$quicksort__4683 invoke "rrb.clj" 219]
  [the_other_datastructures.rrb$eval4682$quicksort__4683 invoke "rrb.clj" 217]
  [the_other_datastructures.rrb$eval4682$quicksort__4683 invoke "rrb.clj" 217]
  [the_other_datastructures.rrb$eval4682$quicksort__4683 invoke "rrb.clj" 217]
  [the_other_datastructures.rrb$eval4682$quicksort__4683 invoke "rrb.clj" 219]
  [the_other_datastructures.rrb$eval4682$quicksort__4683 invoke "rrb.clj" 217]
  [the_other_datastructures.rrb$eval4921 invoke "rrb.clj" 221]
  [clojure.lang.Compiler eval "Compiler.java" 6782]
  [clojure.lang.Compiler load "Compiler.java" 7227]
  [user$eval4909 invoke "form-init3543508351311666483.clj" 1]
  [clojure.lang.Compiler eval "Compiler.java" 6782]
  [clojure.lang.Compiler eval "Compiler.java" 6745]
  [clojure.core$eval invoke "core.clj" 3081]
  [clojure.main$repl$read_eval_print__7099$fn__7102 invoke "main.clj" 240]
  [clojure.main$repl$read_eval_print__7099 invoke "main.clj" 240]
  [clojure.main$repl$fn__7108 invoke "main.clj" 258]
  [clojure.main$repl doInvoke "main.clj" 258]
  [clojure.lang.RestFn invoke "RestFn.java" 1523]
  [clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__623 invoke "interruptible_eval.clj" 58]
  [clojure.lang.AFn applyToHelper "AFn.java" 152]
  [clojure.lang.AFn applyTo "AFn.java" 144]
  [clojure.core$apply invoke "core.clj" 630]
  [clojure.core$with_bindings_STAR_ doInvoke "core.clj" 1868]
  [clojure.lang.RestFn invoke "RestFn.java" 425]
  [clojure.tools.nrepl.middleware.interruptible_eval$evaluate invoke "interruptible_eval.clj" 56]
  [clojure.tools.nrepl.middleware.interruptible_eval$interruptible_eval$fn__665$fn__668 invoke "interruptible_eval.clj" 191]
  [clojure.tools.nrepl.middleware.interruptible_eval$run_next$fn__660 invoke "interruptible_eval.clj" 159]
  [clojure.lang.AFn run "AFn.java" 22]
  [java.util.concurrent.ThreadPoolExecutor runWorker "ThreadPoolExecutor.java" 1145]
  [java.util.concurrent.ThreadPoolExecutor$Worker run "ThreadPoolExecutor.java" 615]
  [java.lang.Thread run "Thread.java" 745]]}
0
_由 jonase_ 发表的评论

不确定这与此有关,但以下表达式抛出了 NPE(将 rrb/catvec 更改为 clojure.core/into 得到预期结果 [])


(nth (iterate pop (nth (iterate #(rrb/catvec [0] %) []) 963)) 963)



#error {
 :cause nil
 :via
 [{:type clojure.lang.Compiler$CompilerException
   :消息 "java.lang.NullPointerException, 编译位置:(/Users/jonasenlund/dev/clojure/the-other-datastructures/src/the-other-datastructures/rrb.clj:201:5)"
   :at [clojure.lang.Compiler load "Compiler.java" 7239]}
  {:类型 java.lang.NullPointerException}
   :消息 nil
   :在 [clojure.core.rrb_vector.nodes$reify__3483 正常 "nodes.clj" 46]}]
 :trace
 [[clojure.core.rrb_vector.nodes$reify__3483 正常 "nodes.clj" 46]
  [clojure.core.rrb_vector.rrbt.Vector popTail "rrbt.clj" 686]
  [clojure.core.rrb_vector.rrbt.Vector popTail "rrbt.clj" 727]
  [clojure.core.rrb_vector.rrbt.Vector pop "rrbt.clj" 487]
  [clojure.lang.RT pop "RT.java" 716]
  [clojure.core$pop 调用 "core.clj" 1409]
  [clojure.lang.Iterate first "Iterate.java" 47]
  [clojure.lang.Iterate next "Iterate.java" 54]
  [clojure.lang.RT nthFrom "RT.java" 867]
  [clojure.lang.RT nth "RT.java" 840]
  [the_other_datastructures.rrb$eval7254 调用 "rrb.clj" 201]
  [clojure.lang.Compiler eval "Compiler.java" 6782]
  [clojure.lang.Compiler load "Compiler.java" 7227]
  [user$eval7241 调用 "form-init121723447646604580.clj" 1]
  [clojure.lang.Compiler eval "Compiler.java" 6782]
  [clojure.lang.Compiler eval "Compiler.java" 6745]
  [clojure.core$eval invoke "core.clj" 3081]
  [clojure.main$repl$read_eval_print__7099$fn__7102 invoke "main.clj" 240]
  [clojure.main$repl$read_eval_print__7099 invoke "main.clj" 240]
  [clojure.main$repl$fn__7108 invoke "main.clj" 258]
  [clojure.main$repl doInvoke "main.clj" 258]
  [clojure.lang.RestFn invoke "RestFn.java" 1523]
  [clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__623 invoke "interruptible_eval.clj" 58]
  [clojure.lang.AFn applyToHelper "AFn.java" 152]
  [clojure.lang.AFn applyTo "AFn.java" 144]
  [clojure.core$apply invoke "core.clj" 630]
  [clojure.core$with_bindings_STAR_ doInvoke "core.clj" 1868]
  [clojure.lang.RestFn invoke "RestFn.java" 425]
  [clojure.tools.nrepl.middleware.interruptible_eval$evaluate invoke "interruptible_eval.clj" 56]
  [clojure.tools.nrepl.middleware.interruptible_eval$interruptible_eval$fn__665$fn__668 invoke "interruptible_eval.clj" 191]
  [clojure.tools.nrepl.middleware.interruptible_eval$run_next$fn__660 invoke "interruptible_eval.clj" 159]
  [clojure.lang.AFn run "AFn.java" 22]
  [java.util.concurrent.ThreadPoolExecutor runWorker "ThreadPoolExecutor.java" 1145]
  [java.util.concurrent.ThreadPoolExecutor$Worker run "ThreadPoolExecutor.java" 615]
  [java.lang.Thread run "Thread.java" 745]]}
0
_评论文本由: michalmarczyk_

再次感谢您提供的错误报告以及后续的关注!您是否愿意将这些测试用例包含在一个补丁中?

关于修复—我可以看到原始问题案例的大致情况,剩下的就是要找到确切的计算错误发生的地方...一旦解决这个问题,我将发布一个新版本。
0

评论文本由: jonase

我为 ClassCastException 和 NullPointerException 添加了失败的测试。由于某种原因,我只能在与 repl 的 ArrayIndexOutOfBoundsException 进行复现。

0
...