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 t...@gnu.org wrote: Alexey Cherkaev alexey.cherk...@gmail.com 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.