Thank you for your explanation. I also suspect there is some subtle
issue with the class file being used by the different constructors.

However, I would be surprised if this behaviour is intended, and that 
the 'hackery' you proposed is the only, and prefered way of solving this.

To better illustrate the core issue, I updated the example slightly
as follows:

Premise: 
defrecordissue.arecord and defrecordissue.protocol constitute some
library.

1. defrecordissue.arecord defines a record type, and a function that
   will return an instance of the record:

    (ns defrecordissue.arecord)

    (defrecord ARecord [])

    (defn make-record
      []
      (->ARecord))

2. defrecordissue.protocol defines a protocol, and extends it to the
   record type defined in 1. It also defines a public function
   intended to be used by libraries:

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

    (defn some-public-fn
      []
      (afn (defrecordissue.arecord/make-record)))

3. defrecordissue.consumer is a consumer of the library, knows
   nothing of any protocols or records, but only wants to call a
   function thats part of the public api:

    (ns defrecordissue.consumer
      (:require [defrecordissue.aprotocol]))
     
    (defrecordissue.aprotocol/some-public-fn)

This fails with the same root cause.

I've created a new branch for this in the GitHub repo.

https://github.com/ragnard/defrecordissue/tree/more-realistic

/Ragge

On Thursday, 18 April 2013 12:19:35 UTC+1, Andrew Sernyak wrote:
>
> I guess extend-type does changes only to generated java class and the var 
> defrecordissue.arecord->ARecord 
> contains the 'old' version of ARecord constructor. Obviously it would be 
> weird for defprotocol to change the variable in another namespace. 
> Especially when you can extend a record from anywhere.
>
> So If you want to create a record that implements your protocol via var 
> from record namespace, you should do some hackery to update that variable. 
> I've done a pull-request for you, but using direct constructor will be more 
> idiomatic
>
> ;
>> ; this won't work unless you update manualy a variable ->ARecord in the 
>> namespace
>> ;
>> ;(defrecordissue.aprotocol/afn (defrecordissue.arecord/->ARecord))
>> ; 
>> ; like
>> (defmacro from-ns[nmsps & body] 
>>   "launches body from namespace"
>>   `(binding 
>>      [*ns* (find-ns ~nmsps)] 
>>        (eval
>>           (quote (do ~@body)))))
>> (from-ns 'defrecordissue.arecord 
>>          (import '(defrecordissue.arecord.ARecord))
>>          (alter-var-root 
>>            ('->ARecord (ns-publics 'defrecordissue.arecord)) 
>>            (fn[x] (fn[] (new ARecord)))))
>> (println  (defrecordissue.aprotocol/afn 
>> (defrecordissue.arecord/->ARecord)))
>> ; 42
>
>
> ndrw 
>

-- 
-- 
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