Tôi gặp phải, với tôi, hành vi hơi ngạc nhiên dường như liên quan đến hồ sơ clojure.Hành vi đáng ngạc nhiên liên quan đến hồ sơ, giao thức và biên soạn
Cách cài đặt như sau:
Một namespace định nghĩa một loại kỷ lục:
(ns defrecordissue.arecord) (defrecord ARecord [])
namespace Một định nghĩa một giao thức, và mở rộng nó vào loại kỷ lục quy định tại 1:
(ns defrecordissue.aprotocol (:require [defrecordissue.arecord]) (:import [defrecordissue.arecord ARecord])) (defprotocol AProtocol (afn [this])) (extend-protocol AProtocol ARecord (afn [this] 42))
Một không gian tên thứ ba xây dựng một thể hiện của bản ghi và gọi hàm giao thức trên bản ghi.
(ns defrecordissue.aot1 (:require [defrecordissue.aprotocol] [defrecordissue.arecord])) (defrecordissue.aprotocol/afn (defrecordissue.arecord/->ARecord))
Khi namespace defrecordissue.aot1 được biên dịch, trong trường hợp của tôi sử dụng lein compile defrecordissue.aot1
, biên soạn không thành công với các ngoại lệ sau đây:
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
Nếu tôi thay đổi 3) để xây dựng các kỷ lục lớp học trực tiếp, như vậy:
(ns defrecordissue.aot2
(:require [defrecordissue.aprotocol]
[defrecordissue.arecord]))
(defrecordissue.aprotocol/afn (defrecordissue.arecord.ARecord.))
Biên dịch thành công.
Nghi ngờ của tôi là điều này liên quan đến cách nào đó liên quan đến http://dev.clojure.org/jira/browse/CLJ-371, nhưng tôi không hiểu chính xác những gì đang xảy ra.
Tôi cũng nên thêm rằng không có lein clean
, quá trình biên dịch thành công lần thứ hai vì lớp học cho bản ghi hiện có sẵn trên đường dẫn lớp học . Vì vậy, tôi có thể giải quyết vấn đề này bằng cách biên dịch AOT- không gian tên xác định loại bản ghi.
Tôi tạo ra một dự án leiningen đơn giản trên GitHub minh họa vấn đề , xem README để sử dụng: https://github.com/ragnard/defrecordissue
Tại sao tôi lại thấy hành vi này, và cách chính xác để tránh nó là gì?
CẬP NHẬT
Tôi đã thêm một chi nhánh mới vào repo GitHub minh họa rõ hơn về vấn đề cốt lõi: https://github.com/ragnard/defrecordissue/tree/more-realistic/
Vấn đề xảy ra bất kể ở đâu (tức là trong đó không gian tên.) Kỷ lục dụ là được xây dựng.
Ý tưởng hay, ngoại trừ cùng một ngoại lệ. Tôi nghĩ 'defrecordissue.arecord' sẽ được nạp đầu tiên trong mọi trường hợp, vì nó cũng được yêu cầu trong' defrecordissue.aprotocol' – Ragge
Nhận xét trên có liên quan đến một nhận xét khác dường như đã bị xoá. – Ragge