请在2024年Clojure调查问卷中分享您的想法!

欢迎!请参阅关于页面以了解更多关于如何使用本站的信息。

+1
ClojureScript

定义一个使用可变参数的多重方法,然后在具有超过20个项的可序列化对象上使用apply时失败。

错误会根据是否有正好21个参数或更多而有所不同。

这种行为在普通函数定义中不会观察到。

ClojureScript 1.10.439
cljs.user=> (defmulti foo (fn [& args] (first args)))

'cljs.user/foo

cljs.user=> (defmethod foo 0 [& args])

object(link: cljs.core.MultiFn)

cljs.user=> (apply foo (range 20))
nil

cljs.user=> (apply foo (range 21))
错误:20不是ISeqable

 cljs$core$seq (.cljs_nashorn_repl/cljs/core.cljs:1223:13)
 cljs$core$spread (.cljs_nashorn_repl/cljs/core.cljs:3739:9)
 cljs$core$spread (.cljs_nashorn_repl/cljs/core.cljs:3740:9)
 cljs$core$spread (.cljs_nashorn_repl/cljs/core.cljs:3740:9)
 cljs$core$spread (.cljs_nashorn_repl/cljs/core.cljs:3740:9)
 cljs$core$spread (.cljs_nashorn_repl/cljs/core.cljs:3740:9)
 cljs$core$spread (.cljs_nashorn_repl/cljs/core.cljs:3740:9)
 cljs$core$spread (.cljs_nashorn_repl/cljs/core.cljs:3740:9)
 cljs$core$spread (.cljs_nashorn_repl/cljs/core.cljs:3740:9)
 cljs$core$spread (.cljs_nashorn_repl/cljs/core.cljs:3740:9)
 cljs$core$spread (.cljs_nashorn_repl/cljs/core.cljs:3740:9)
 cljs$core$spread (.cljs_nashorn_repl/cljs/core.cljs:3740:9)
 cljs$core$spread (.cljs_nashorn_repl/cljs/core.cljs:3740:9)
 cljs$core$spread (.cljs_nashorn_repl/cljs/core.cljs:3740:9)
 cljs$core$spread (.cljs_nashorn_repl/cljs/core.cljs:3740:9)
 cljs$core$spread (.cljs_nashorn_repl/cljs/core.cljs:3740:9)
 cljs$core$spread (.cljs_nashorn_repl/cljs/core.cljs:3740:9)
 cljs$core$spread (.cljs_nashorn_repl/cljs/core.cljs:3740:9)
 cljs$core$IFn$_invoke$arity$variadic (.cljs_nashorn_repl/cljs/core.cljs:3926:6)
 G__12749__22 (.cljs_nashorn_repl/cljs/core.cljs:10998:5)
 G__12749 (.cljs_nashorn_repl/cljs/core.cljs:10868:1)
 apply (.cljs_nashorn_repl/cljs/core.cljs:10868:1)
 cljs$core$IFn$_invoke$arity$6 (.cljs_nashorn_repl/cljs/core.cljs:3885:6)
 cljs$core$IFn$_invoke$arity$5 (.cljs_nashorn_repl/cljs/core.cljs:3879:6)
 cljs$core$IFn$_invoke$arity$4 (.cljs_nashorn_repl/cljs/core.cljs:3873:6)
 cljs$core$IFn$_invoke$arity$3 (.cljs_nashorn_repl/cljs/core.cljs:3867:6)
 cljs$core$IFn$_invoke$arity$2 (.cljs_nashorn_repl/cljs/core.cljs:3861:6)
 cljs$core$IFn$_invoke$arity$2 (.cljs_nashorn_repl/cljs/core.cljs:3896:6)
 cljs$core$apply (.cljs_nashorn_repl/cljs/core.cljs:3887:1)
 (<NO_SOURCE_FILE> <eval>:1:0)
 (<NO_SOURCE_FILE> <eval>:1:0)
 (<NO_SOURCE_FILE> <eval>:1:0)

cljs.user=> (apply foo (range 22))
错误:无效的arity:22

 G__12749 (.cljs_nashorn_repl/cljs/core.cljs:36125:0)
 apply (.cljs_nashorn_repl/cljs/core.cljs:10868:1)
 cljs$core$IFn$_invoke$arity$6 (.cljs_nashorn_repl/cljs/core.cljs:3885:6)
 cljs$core$IFn$_invoke$arity$5 (.cljs_nashorn_repl/cljs/core.cljs:3879:6)
 cljs$core$IFn$_invoke$arity$4 (.cljs_nashorn_repl/cljs/core.cljs:3873:6)
 cljs$core$IFn$_invoke$arity$3 (.cljs_nashorn_repl/cljs/core.cljs:3867:6)
 cljs$core$IFn$_invoke$arity$2 (.cljs_nashorn_repl/cljs/core.cljs:3861:6)
 cljs$core$IFn$_invoke$arity$2 (.cljs_nashorn_repl/cljs/core.cljs:3896:6)
 cljs$core$apply (.cljs_nashorn_repl/cljs/core.cljs:3887:1)
 (<NO_SOURCE_FILE> <eval>:1:0)
 (<NO_SOURCE_FILE> <eval>:1:0)
 (<NO_SOURCE_FILE> <eval>:1:0)

cljs.user=> (defn bar [& args])

'cljs.user/bar

cljs.user=> (apply bar (range 100))
nil

2个回答

0

评论者:kanaka

我认为这是相同的问题或与之密切相关:https://clojure.atlassian.net/browse/CLJS-2446

我在实际情况下遇到过我认为是相同的问题(使用ClojureScript的自宿主mal/make-a-lisp)。似乎带有元数据的函数有与多重方法相同的限制。

以下展示了使用lumo的使用方法,但同一问题在使用在浏览器中(Chrome)运行的AOT cljs时也存在。

`
Lumo 1.10.1
ClojureScript 1.10.520
Node.js v11.13.0
...
cljs.user=> (apply + (range 20))
190
cljs.user=> (apply + (range 21))
210
cljs.user=> (apply + (range 22))
231

cljs.user=> (apply (with-meta + {}) (range 20))
190
cljs.user=> (apply (with-meta + {}) (range 21))
20不是ISeqable

 Object.cljs.core.seq (NO_SOURCE_FILE <embedded>:503:388)
 Object.cljs.core.spread (NO_SOURCE_FILE <embedded>:834:335)
 Object.cljs.core.spread (NO_SOURCE_FILE <embedded>:834:500)
 Object.cljs.core.spread (NO_SOURCE_FILE <embedded>:834:500)
 Object.cljs.core.spread (NO_SOURCE_FILE <embedded>:834:500)
 Object.cljs.core.spread (NO_SOURCE_FILE <embedded>:834:500)
 Object.cljs.core.spread (NO_SOURCE_FILE <embedded>:834:500)
 Object.cljs.core.spread (NO_SOURCE_FILE <embedded>:834:500)
 Object.cljs.core.spread (NO_SOURCE_FILE <embedded>:834:500)
 Object.cljs.core.spread (NO_SOURCE_FILE <embedded>:834:500)

cljs.user=> (apply (with-meta + {}) (range 22))
Invalid arity: 22

 (cljs.core.MetaFn.a)
 cljs.core.MetaFn.apply (NO_SOURCE_FILE <embedded>:603:289)
 Function.cljs.core.apply_to_simple.cljs$core$IFn$_invoke$arity$6 (NO_SOURCE_FILE <embedded>:874:323)
 Function.cljs.core.apply_to_simple.cljs$core$IFn$_invoke$arity$5 (NO_SOURCE_FILE <embedded>:867:205)
 Function.cljs.core.apply_to_simple.cljs$core$IFn$_invoke$arity$4 (NO_SOURCE_FILE <embedded>:866:199)
 Function.cljs.core.apply_to_simple.cljs$core$IFn$_invoke$arity$3 (NO_SOURCE_FILE <embedded>:865:193)
 Function.cljs.core.apply_to_simple.cljs$core$IFn$_invoke$arity$2 (NO_SOURCE_FILE <embedded>:864:188)
 Function.cljs.core.apply.cljs$core$IFn$_invoke$arity$2 (NO_SOURCE_FILE <embedded>:877:244)
 cljs.core.apply (NO_SOURCE_FILE <embedded>:875:84)
 (evalmachine.<anonymous>:1:17)

`

我来这里是为了报告这个问题,我很高兴找到了这个问题。我在任何有元数据的任何地方都看到了同样的情况,实际上任何实现了 `IFn` 的地方也是如此。

```
(let [args (repeat 21 0)]
  (apply (with-meta + {}) args))
```
0
参考: https://clojure.atlassian.net/browse/CLJS-3024(由 alex+import 提出)
...