私には、やや驚くべき振る舞いが見受けられました。一見、 がクロージャレコードに関連しています。次のようにレコード、プロトコル、コンパイルに関連する驚くべき振る舞い
設定は次のとおり
名前空間は、レコードタイプ定義の一つ:
(ns defrecordissue.arecord) (defrecord ARecord [])
別の名前空間は、プロトコルを定義し、1で定義されたレコード 型に延びています。
(ns defrecordissue.aprotocol (:require [defrecordissue.arecord]) (:import [defrecordissue.arecord ARecord])) (defprotocol AProtocol (afn [this])) (extend-protocol AProtocol ARecord (afn [this] 42))
第3の名前空間レコードのインスタンスを構築し、レコード上のプロトコル関数 を呼び出します。
(ns defrecordissue.aot1 (:require [defrecordissue.aprotocol] [defrecordissue.arecord])) (defrecordissue.aprotocol/afn (defrecordissue.arecord/->ARecord))
defrecordissue.aot1名前空間が lein compile defrecordissue.aot1
を使用して、私の場合には、コンパイルされた場合、コンパイルが 次の例外で失敗します。私は3を変更した場合
Exception in thread "main" java.lang.IllegalArgumentException: No implementation of method: :afn of protocol: #'defrecordissue.aprotocol/AProtocol found for class: defrecordissue.arecord.ARecord, compiling:(aot1.clj:5:1)
at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3463)
at clojure.lang.Compiler.compile1(Compiler.java:7153)
at clojure.lang.Compiler.compile(Compiler.java:7219)
at clojure.lang.RT.compile(RT.java:398)
at clojure.lang.RT.load(RT.java:438)
at clojure.lang.RT.load(RT.java:411)
at clojure.core$load$fn__5018.invoke(core.clj:5530)
at clojure.core$load.doInvoke(core.clj:5529)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invoke(core.clj:5336)
at clojure.core$compile$fn__5023.invoke(core.clj:5541)
at clojure.core$compile.invoke(core.clj:5540)
at user$eval7.invoke(NO_SOURCE_FILE:1)
at clojure.lang.Compiler.eval(Compiler.java:6619)
at clojure.lang.Compiler.eval(Compiler.java:6609)
at clojure.lang.Compiler.eval(Compiler.java:6582)
at clojure.core$eval.invoke(core.clj:2852)
at clojure.main$eval_opt.invoke(main.clj:308)
at clojure.main$initialize.invoke(main.clj:327)
at clojure.main$null_opt.invoke(main.clj:362)
at clojure.main$main.doInvoke(main.clj:440)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at clojure.lang.Var.invoke(Var.java:419)
at clojure.lang.AFn.applyToHelper(AFn.java:163)
at clojure.lang.Var.applyTo(Var.java:532)
at clojure.main.main(main.java:37)
Caused by: java.lang.IllegalArgumentException: No implementation of method: :afn of protocol: #'defrecordissue.aprotocol/AProtocol found for class: defrecordissue.arecord.ARecord
at clojure.core$_cache_protocol_fn.invoke(core_deftype.clj:541)
at defrecordissue.aprotocol$fn__40$G__35__45.invoke(aprotocol.clj:5)
at clojure.lang.AFn.applyToHelper(AFn.java:161)
at clojure.lang.AFn.applyTo(AFn.java:151)
at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3458)
... 25 more
)レコードを構築します直接のように、クラス:
(ns defrecordissue.aot2
(:require [defrecordissue.aprotocol]
[defrecordissue.arecord]))
(defrecordissue.aprotocol/afn (defrecordissue.arecord.ARecord.))
コンパイルに成功しました。
私の疑惑は、これは何とか http://dev.clojure.org/jira/browse/CLJ-371に関連しているということですが、私は が正確に何が起こっているのか理解していません。
私はまた、レコードのクラスが クラスパス上で使用できるようになりましたので、lein clean
せず、コンパイルは、 二度目に成功したことを追加する必要があります。したがって、この問題を回避するには、レコードタイプを定義するネームスペース をAOTコンパイルしてください。私は 問題を示してGitHubの上の簡単なLeiningenをプロジェクトを作成し
、使用方法については、READMEを参照してください。 https://github.com/ragnard/defrecordissue
は、なぜ私はこの振る舞いを見ていて、それを回避するための正しい方法は何ですか?
UPDATE
私はより良いコアの問題を示すGitHubのレポに新しいブランチを追加しました: https://github.com/ragnard/defrecordissue/tree/more-realistic/
問題は関係なく、どこの発生記録 インスタンスである(つまり、その名前空間に。)構築された。
いい考えですが、同じ例外です。私は 'defrecordissue.arecord'が最初にロードされると思います。なぜなら、' defrecordissue.aprotocol'の中でも必要であるからです。 – Ragge
上記のコメントは明らかに削除された別のコメントに関連していました。 – Ragge