Hi,

Today I encountered a, to me, slightly surprising behaviour seemingly
related clojure records. 

The setup is as follows:

1. One namespace defines a record type:

    (ns defrecordissue.arecord)

    (defrecord ARecord [])


2. Another namespace defines a protocol, and extends it to the record
   type defined in 1:

    (ns defrecordissue.aprotocol
      (:require [defrecordissue.arecord])
      (:import [defrecordissue.arecord ARecord]))
     
    (defprotocol AProtocol
      (afn [this]))
     
    (extend-protocol AProtocol
      ARecord
      (afn [this] 42))

3. A third namespace constructs an instance of the record and invokes
   the protocol function on the record:

    (ns defrecordissue.aot1
      (:require [defrecordissue.aprotocol]
                [defrecordissue.arecord]))
     
    (defrecordissue.aprotocol/afn (defrecordissue.arecord/->ARecord))


When the defrecordissue.aot1 namespace is compiled, in my case using
`lein compile defrecordissue.aot1`, compilation fails with the
following exception:

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 

If I change 3) to construct the record class directly, like so:

   (ns defrecordissue.aot2
     (:require [defrecordissue.aprotocol]
               [defrecordissue.arecord]))
    
   (defrecordissue.aprotocol/afn (defrecordissue.arecord.ARecord.))

Compilation succeeds.

My suspicion is that this is somehow related to
http://dev.clojure.org/jira/browse/CLJ-371, but I don't understant
exactly what is happening. 

I should also add that without the `lein clean`, compilation succeeds
the second time, since a class for the record is now available on the
classpath. Therefore, I can get around this problem by AOT-compiling
the namespace defining the record type.

I created a simple leiningen project on GitHub that illustrates the
issue, see README for usage:
https://github.com/ragnard/defrecordissue

Any enlightenment is much appreciated.

Cheers,

Ragnar

-- 
-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to