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. 抛出上述提到的类转换异常 (~60%)


#error {
 :原因 "clojure.lang.PersistentVector$Node 无法转换到 [I"
 :via
 [{:类型 clojure.lang.Compiler$CompilerException}
   :信息 "java.lang.ClassCastException: clojure.lang.PersistentVector$Node cannot be cast to [I, 源文件:(Users/jonasenlund/dev/clojure/the-other-datastructures/src/the-other-datastructures/rrb.clj:221:1)"
   :在 [clojure.lang.Compiler load "Compiler.java" 7239]}
  {:类型 java.lang.ClassCastException}
   :信息 "clojure.lang.PersistentVector$Node cannot be cast to [I"
   :在 [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.langompiler eval "Compiler.java" 6782]
  [clojure.langompiler load "Compiler.java" 7227]
  [user$eval4909 invoke "form-init3543508351311666483.clj" 1]
  [clojure.langompiler eval "Compiler.java" 6782]
  [clojure.langompiler 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 制作的评论

我不确定这与否有关,但以下表达式抛出一个空指针异常(将 rrb/catvec 修改为 clojure.core/into 可得到预期结果 [])


(从迭代pop中得到的nth,迭代自nth(迭代rrb/catvec [0] % [] 963)的结果的第963个元素)



#error {
 :cause nil
 :via
 [{:类型 clojure.lang.Compiler$CompilerException}
   :message "java.lang.NullablePointerException,在编译文件:(/Users/jonasenlund/dev/clojure/the-other-datastructures/src/the_other_datastructures/rrb.clj:201行:5处)"
   :在 [clojure.lang.Compiler load "Compiler.java" 7239]}
  {:type java.lang.NullablePointerException}
   :message nil
   :at [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.langompiler eval "Compiler.java" 6782]
  [clojure.langompiler load "Compiler.java" 7227]
  [user$eval7241 调用 "form-init121723447646604580.clj" 1]
  [clojure.langompiler eval "Compiler.java" 6782]
  [clojure.langompiler 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_作出

再次感谢您提供的bug报告,并对后续的跟进表示深深的感谢!您是否愿意将这些测试用例包装在一个补丁中?

至于修复 - 我可以大致了解原始问题案例中发生了什么,剩下的工作是需要找出精确的错误计算发生在哪里…一旦解决,我会发布新版本。
0

评论由:jonase

我添加了对ClassCastException和NullPointerException的失败测试。由于某种原因,我只能在repl中重现ArrayIndexOutOfBoundsException。

0
参考:https://clojure.atlassian.net/browse/CRRBV-12 (由jonase报告)
...