Re: extend-type and extend-protocol: different syntax for multi-arity methods
Hi Tassilo, Thanks for the reply. The thing is, although the implementations for extending protocols directly in records and with extend-type might be different, there is no reason why the syntax should be different: from Clojure-programmer perspective it’s all the same. It is a leaked abstraction if we have to thing about those details. The same applies for interface implementation: overloaded methods there and multi-arity functions in Clojure shouldn’t look differently to a Clojure programmer (unless there is some more profound difference). Best regards, Alexey On 13 May 2015 at 14:46, Tassilo Horn wrote: > Alexey Cherkaev writes: > > Hi Alexey, > > > If you have a protocol > > > > (defprotocol Foo (foo [x] [x y])) > > > > and implement it for the record > > > > (defrecord Bar [p q r] > > Foo > > (foo [x] x) > > (foo [x y] [x y])) > > > > you write each method separately. The same is true for extend-type. > > Yet, if you use extend-protocol syntax is more like usual Clojure > > multi-arity function definition: > > > > (extend-protocol Foo > > Bar > > (foo > > ([x] x) > > ([x y] [x y]))) > > > > The first question is why there is a difference? > > I think, the difference is that deftype/defrecord create an interface > (and an implementation class) under the hoods, and there, the different > arities of foo are actually different methods. > > extend/extend-type/extend-protocol dynamically extend a protocol to some > type. Basically, the protocol's underlying dynamic dispatch table gets > a new [type impl-function] entry where impl-function is a real Clojure > function, thus you must specify all arities you want to support the > normal Clojure way. > > > Secondly, if you mess up which syntax is where, the error you will get > > is quite obscure, nothing guards you against essentially a *wrong > > syntax*: both extend-type and extend-protocol are macros, so it > > shouldn’t be too difficult to add a quick check on correctness. > > Yeah, for extend-protocol/extend-type the standard multi-arity syntax is > the only correct one. > > > But lastly, wouldn’t it be better to have a uniform syntax? > > The problem is that defrecord and deftype also allow for implementing > interfaces. If Foo above was an interface, foo with 1 argument and foo > with 2 arguments are completely separate methods (ok, they overload), > thus it makes sense to define them separately. However, if Foo was a > protocol, it would also make sense to notate it as multi-arity function. > But then you have an inconsistent syntax inside defrecord/deftype. > Well, although one could argue that this was a good thing because it > would allow to see immediately if Foo was a protocol or an interface. > > Bye, > Tassilo > -- 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/d/optout.
extend-type and extend-protocol: different syntax for multi-arity methods
Hi all, If you have a protocol (defprotocol Foo (foo [x] [x y])) and implement it for the record (defrecord Bar [p q r] Foo (foo [x] x) (foo [x y] [x y])) you write each method separately. The same is true for extend-type. Yet, if you use extend-protocol syntax is more like usual Clojure multi-arity function definition: (extend-protocol Foo Bar (foo ([x] x) ([x y] [x y]))) The first question is why there is a difference? Secondly, if you mess up which syntax is where, the error you will get is quite obscure, nothing guards you against essentially a *wrong syntax*: both extend-type and extend-protocol are macros, so it shouldn’t be too difficult to add a quick check on correctness. But lastly, wouldn’t it be better to have a uniform syntax? Regards, Alexey -- 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/d/optout.
Re: Strange behaviour of a callable record
Thanks, Nicola! It solved it. When I looked at docs, I couldn't figure out the role of `applyTo`. Well, now I know. On Thursday, April 23, 2015 at 1:47:11 PM UTC+2, Nicola Mometto wrote: > > > You're not implementing IFn.applyTo, you should. > > Why applyTo is used in the second example while invoke is used in the > other cases has to do with implementation details of how def expressions > are compiled/evaluated. > > Alexey Cherkaev writes: > > > Hi, > > > > I have encountered the problem with Clojure 1.6.0, when I create the > record > > that implements IFn. > > > > For example, > > > > (defrecord Foo [x] > > clojure.lang.IFn > > (invoke [_ f] (f x))) > > > > Than create an instance of this record: > > > > (def f (->Foo 10)) > > > > And we can call it without a problem: > > > > user=> (f inc) > > 11 > > > > Yet, if you try to define a value to keep the result, compiler throws an > > error: > > > > user=> (def z (f inc)) > > > > CompilerException java.lang.AbstractMethodError, > > compiling:(form-init4774307052978984831.clj:1:8) > > > > There is workaround: create local binding first and then assign the > value > > to a global variable: > > > > user=> (def z (let [temp (f inc)] temp)) > > #'user/z > > user=> z > > 11 > > > > Is this a bug or I don't fully understand why you can't do that? > > > > Cheers, Alexey > > -- > -- 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/d/optout.
Strange behaviour of a callable record
Hi, I have encountered the problem with Clojure 1.6.0, when I create the record that implements IFn. For example, (defrecord Foo [x] clojure.lang.IFn (invoke [_ f] (f x))) Than create an instance of this record: (def f (->Foo 10)) And we can call it without a problem: user=> (f inc) 11 Yet, if you try to define a value to keep the result, compiler throws an error: user=> (def z (f inc)) CompilerException java.lang.AbstractMethodError, compiling:(form-init4774307052978984831.clj:1:8) There is workaround: create local binding first and then assign the value to a global variable: user=> (def z (let [temp (f inc)] temp)) #'user/z user=> z 11 Is this a bug or I don't fully understand why you can't do that? Cheers, Alexey -- 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/d/optout.