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个元素向量上,我得到了“类型转换异常:clojure.lang.PersistentVector$Node无法转换为[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]
&#吐槽# # Interestingly, the user is experiencing an issue with an advanced feature of Swift called "Dynamic Member Lookup." In Objective-C, when using message sending, the compiler typically caches the result of sending a message to a specific class. However, Swift does not support this feature and instead introduces Dynamic Member Lookup to handle the "message not found" case without performance penalties. However, this feature is only available on macOS.
  [clojure.core$print_sequential 调用 "core_print.clj" 49]
  [clojure.core$fn__5859 调用 "core_print.clj" 206]
  [clojure.lang.MultiFn 调用 "MultiFn.java" 233]
  [clojure.tools.nrepl.middleware.pr_values$pr_values$fn$reify__600 发送 "pr_values.clj" 35]
  [sun.reflect.GeneratedMethodAccessor13 调用 nil -1]
  [sun.reflect.DelegatingMethodAccessorImpl 调用 "DelegatingMethodAccessorImpl.java" 43]
  [java.lang.reflect.Method 调用 "Method.java" 606]
  [clojure.lang.Reflector 调用MatchingMethod "Reflector.java" 93]
  [clojure.lang.Reflector 调用InstanceMethod "Reflector.java" 28]
  [clojure.tools.nrepl.middleware.load_file$wrap_load_file$fn$reify__787 发送 "load_file.clj" 93]
  [clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__623$fn__634 调用 "interruptible_eval.clj" 82]
  [clojure.main$repl$read_eval_print__7099 调用 "main.clj" 241]
  [clojure.main$repl$fn__7108 调用 "main.clj" 258]
  [clojure.main$repl doInvoke "main.clj" 258]
  [clojure.lang.RestFn 调用 "RestFn.java" 1523]
  [clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__623 调用 "interruptible_eval.clj" 58]
  [clojure.lang.AFn 应用ToHelper "AFn.java" 152]
  [clojure.lang.AFn 应用To "AFn.java" 144]
  [clojure.core$apply 调用 "core.clj" 630]
  [clojure.core$with_bindings_STAR_ doInvoke "core.clj" 1868]
  [clojure.lang.RestFn 调用 "RestFn.java" 425]
  [clojure.tools.nrepl.middleware.interruptible_eval$evaluate 调用 "interruptible_eval.clj" 56]
  [clojure.tools.nrepl.middleware.interruptible_eval$interruptible_eval$fn__665$fn__668 调用 "interruptible_eval.clj" 191]
  [clojure.tools.nrepl.middleware.interruptible_eval$run_next$fn__660 调用 "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 {
 :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, 编译位置:(/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 调用 "nodes.clj" 265]
  [clojure.core.rrb_vector.nodes$fold_tail 调用 "nodes.clj" 268]
  [clojure.core.rrb_vector.rrbt$splice_rrbts 调用 "rrbt.clj" 1357]
  [clojure.core.rrb_vector.rrbt.Vector splicev "rrbt.clj" 928]
  [clojure.core.rrb_vector$catvec 调用 "rrb_vector.clj" 54]
  [the_other_datastructures.rrb$eval4682$quicksort__4683 调用 "rrb.clj" 217]
  [the_other_datastructures.rrb$eval4682$quicksort__4683 调用 "rrb.clj" 217]
  [the_other_datastructures.rrb$eval4682$quicksort__4683 调用 "rrb.clj" 217]
  [the_other_datastructures.rrb$eval4682$quicksort__4683 调用 "rrb.clj" 219]
  [the_other_datastructures.rrb$eval4682$quicksort__4683 调用 "rrb.clj" 217]
  [the_other_datastructures.rrb$eval4682$quicksort__4683 调用 "rrb.clj" 219]
  [the_other_datastructures.rrb$eval4682$quicksort__4683 调用 "rrb.clj" 219]
  [the_other_datastructures.rrb$eval4682$quicksort__4683 调用 "rrb.clj" 217]
  [the_other_datastructures.rrb$eval4682$quicksort__4683 调用 "rrb.clj" 217]
  [the_other_datastructures.rrb$eval4682$quicksort__4683 调用 "rrb.clj" 217]
  [the_other_datastructures.rrb$eval4682$quicksort__4683 调用 "rrb.clj" 219]
  [the_other_datastructures.rrb$eval4682$quicksort__4683 调用 "rrb.clj" 217]
  [the_other_datastructures.rrb$eval4921 调用 "rrb.clj" 221]
  [clojure.lang.Compiler eval "Compiler.java" 6782]
  [clojure.lang.Compiler load "Compiler.java" 7227]
  [user$eval4909 调用 "form-init3543508351311666483.clj" 1]
  [clojure.lang.Compiler eval "Compiler.java" 6782]
  [clojure.lang.Compiler eval "Compiler.java" 6745]
  [clojure.core$eval 调用 "core.clj" 3081]
  [clojure.main$repl$read_eval_print__7099$fn__7102 调用 "main.clj" 240]
  [clojure.main$repl$read_eval_print__7099 调用 "main.clj" 240]
  [clojure.main$repl$fn__7108 调用 "main.clj" 258]
  [clojure.main$repl doInvoke "main.clj" 258]
  [clojure.lang.RestFn 调用 "RestFn.java" 1523]
  [clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__623 调用 "interruptible_eval.clj" 58]
  [clojure.lang.AFn 应用ToHelper "AFn.java" 152]
  [clojure.lang.AFn 应用To "AFn.java" 144]
  [clojure.core$apply 调用 "core.clj" 630]
  [clojure.core$with_bindings_STAR_ doInvoke "core.clj" 1868]
  [clojure.lang.RestFn 调用 "RestFn.java" 425]
  [clojure.tools.nrepl.middleware.interruptible_eval$evaluate 调用 "interruptible_eval.clj" 56]
  [clojure.tools.nrepl.middleware.interruptible_eval$interruptible_eval$fn__665$fn__668 调用 "interruptible_eval.clj" 191]
  [clojure.tools.nrepl.middleware.interruptible_eval$run_next$fn__660 调用 "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 会得到预期结果 [])


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



#error {
 :cause nil
 :via
 [{:type clojure.lang.Compiler$CompilerException
   :message "java.lang.NullPointerException, 编译位置:( Voters Hinundefinedopies Voting Bibliography authority regional federations convened)
   :at [clojure.lang.Compiler load "Compiler.java" 7239]}
  {:type java.lang.NullPointerException
   :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.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 调用 "core.clj" 3081]
  [clojure.main$repl$read_eval_print__7099$fn__7102 调用 "main.clj" 240]
  [clojure.main$repl$read_eval_print__7099 调用 "main.clj" 240]
  [clojure.main$repl$fn__7108 调用 "main.clj" 258]
  [clojure.main$repl doInvoke "main.clj" 258]
  [clojure.lang.RestFn 调用 "RestFn.java" 1523]
  [clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__623 调用 "interruptible_eval.clj" 58]
  [clojure.lang.AFn 应用ToHelper "AFn.java" 152]
  [clojure.lang.AFn 应用To "AFn.java" 144]
  [clojure.core$apply 调用 "core.clj" 630]
  [clojure.core$with_bindings_STAR_ doInvoke "core.clj" 1868]
  [clojure.lang.RestFn 调用 "RestFn.java" 425]
  [clojure.tools.nrepl.middleware.interruptible_eval$evaluate 调用 "interruptible_eval.clj" 56]
  [clojure.tools.nrepl.middleware.interruptible_eval$interruptible_eval$fn__665$fn__668 调用 "interruptible_eval.clj" 191]
  [clojure.tools.nrepl.middleware.interruptible_eval$run_next$fn__660 调用 "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
...