Ah yes. I didn't consider that. On Wednesday, January 15, 2020 at 12:31:13 PM UTC-5, Alex Miller wrote: > > Using vars lets you iterate on the impl functions without invalidating the > proxy instances. I'm not sure if that was the reason, but that would be one > advantage. > > On Wednesday, January 15, 2020 at 10:46:36 AM UTC-6, Mike Rodriguez wrote: >> >> Do you have any idea about the reason that the Clojure implementation was >> done this way - when it obviously seems a bit limited and also slower than >> necessary? Just curious if there's some historical context. >> >> On Tuesday, January 14, 2020 at 11:58:17 AM UTC-5, Nathan Marz wrote: >>> >>> The speedup comes from proxy+ directly overriding methods with the >>> provided implementation, while Clojure's proxy has additional indirection. >>> For example, if you do (proxy [Object] [] (toString [] "hello")), the >>> bytecode for toString is: >>> >>> public java.lang.String toString(); >>> >>> 0 aload_0 [this] >>> >>> 1 getfield user.proxy$java.lang.Object$ff19274a.__clojureFnMap : >>> clojure.lang.IPersistentMap [16] >>> >>> 4 ldc <String "toString"> [52] >>> >>> 6 invokestatic clojure.lang.RT.get(java.lang.Object, >>> java.lang.Object) : java.lang.Object [36] >>> >>> 9 dup >>> >>> 10 ifnull 28 >>> >>> 13 checkcast clojure.lang.IFn [38] >>> >>> 16 aload_0 [this] >>> >>> 17 invokeinterface clojure.lang.IFn.invoke(java.lang.Object) : >>> java.lang.Object [55] [nargs: 2] >>> >>> 22 checkcast java.lang.String [57] >>> >>> 25 goto 33 >>> >>> 28 pop >>> >>> 29 aload_0 [this] >>> >>> 30 invokespecial java.lang.Object.toString() : java.lang.String >>> [59] >>> >>> 33 areturn >>> >>> Clojure keeps the implementations in a map, and for every dispatch it >>> does a map lookup by the method name. This is also why it can't handle >>> overriding the same method name with different arities. >>> >>> For (proxy+ [] Object (toString [this] "hello")), the bytecode is: >>> >>> public java.lang.String toString(); >>> >>> 0 aload_0 [this] >>> >>> 1 getfield user.proxy_plus5358.toString5357 : clojure.lang.IFn >>> [19] >>> >>> 4 aload_0 [this] >>> >>> 5 invokeinterface clojure.lang.IFn.invoke(java.lang.Object) : >>> java.lang.Object [30] [nargs: 2] >>> >>> 10 checkcast java.lang.String [32] >>> >>> 13 areturn >>> >>> The implementation function is stored as a field, so the cost of >>> dispatch is a field get rather than a map lookup. >>> >>> Clojure's proxy also overrides *every* available method in all >>> superclasses/interfaces, while proxy+ only overrides what you specify. So >>> proxy+ generates much smaller classes than proxy. >>> >>> >>> On Tuesday, January 14, 2020 at 10:30:32 AM UTC-5, Brent Millare wrote: >>>> >>>> I skimmed the code, I don't really understand how it makes it faster >>>> over proxy. Is it the generated ASM is better? What's the in-a-nutshell >>>> description of how it works? >>>> >>>> On Monday, January 13, 2020 at 1:28:46 PM UTC-5, Nathan Marz wrote: >>>>> >>>>> No differences in behavior except for API being like reify. It >>>>> integrates with AOT and can be consumed just like any other class. No >>>>> idea >>>>> how it interacts with Graal. >>>>> >>>>> On Monday, January 13, 2020 at 12:29:35 PM UTC-5, John Newman wrote: >>>>>> >>>>>> Bravo 👏👏👏👏👏 >>>>>> >>>>>> Are there any differences in behavior to be aware of? AOT, Graal, >>>>>> consuming proxy+ classes from vanilla clojure classes? >>>>>> >>>>>> On Mon, Jan 13, 2020, 11:47 AM Nathan Marz <natha...@gmail.com> >>>>>> wrote: >>>>>> >>>>>>> proxy+ is a replacement for Clojure's proxy that's faster and more >>>>>>> usable. proxy has a strange implementation where it overrides every >>>>>>> possible method and uses a mutable field to store a map of string -> >>>>>>> function for dispatching the methods. This causes it to be unable to >>>>>>> handle >>>>>>> methods with the same name but different arities. >>>>>>> >>>>>>> proxy+ fixes these issues with proxy. Usage is like reify, and it's >>>>>>> up to 10x faster. >>>>>>> >>>>>>> *Repository: *https://github.com/redplanetlabs/proxy-plus >>>>>>> >>>>>>> -- >>>>>>> You received this message because you are subscribed to the Google >>>>>>> Groups "Clojure" group. >>>>>>> To post to this group, send email to clo...@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 >>>>>>> clo...@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 clo...@googlegroups.com. >>>>>>> To view this discussion on the web visit >>>>>>> https://groups.google.com/d/msgid/clojure/6d9bf48a-c5b5-417a-9f66-aa494cc38346%40googlegroups.com >>>>>>> >>>>>>> <https://groups.google.com/d/msgid/clojure/6d9bf48a-c5b5-417a-9f66-aa494cc38346%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>>>> . >>>>>>> >>>>>>
-- 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. To view this discussion on the web visit https://groups.google.com/d/msgid/clojure/b9597e05-be8d-4213-a33c-acc90a17c4ad%40googlegroups.com.