Hi Atamert, Here's a gist with the example code: https://gist.github.com/neapel/4e502a14e3738b709672
I tried replacing a closure with a dynamically built and evaluated >> metafunction but discovered that it was actually slower. >> > > If evaluating code during run is slower than AOT compiling it, it wouldn't > surprise me. > I didn't actually try AOT compiling it, just using the REPL. As far as I understand there shouldn't be a difference in speed, since (eval) runs the same compiler as AOT does, and even writes out a .class file. (possibly unrelated, maybe due to eval, when trying to AOT compile the example project by adding `:aot :all` and running `lein jar`, it appears to fall into an infinite loop. The JAR file grew to 8GB, but I couldn't list its contents.) > I guess f2 runs this much slower than f1 because it doesn't actually pass >> a reference to x when unquoting, but clones the value, which means it needs >> to compare the lists element-wise. >> > > This is interesting. Were you able to confirm it or are you just guessing? > (I'm just curious.) > The code in the Gist produces a nice table now, here's my result (I couldn't reproduce the case where f3 runs as fast as f1 for vectors; but it's actually less weird this way) I think it's quite obvious that f1 compares always references, as does the "nil" case, while the "vec" and "map" cases compare by value: | map | vec | nil | name | |--------+--------+------+------| | 5 ns | 5 ns | 5 ns | f1 | | 558 ns | 134 ns | 6 ns | f2 | | 567 ns | 130 ns | 7 ns | f3 | | 561 ns | 117 ns | 7 ns | f4 | It also dumps the disassembly, we can see that: f1-map == f1-vec == f1-nil (makes sense, as the reference to the value is passed in the constructor of the closure) f2-map = f3-map, f2-vec = f3-vec, f2-nil = f3-nil (with renaming) f4-map = f1, f4-vec = f1, f4-nil = f1 (with renaming) f2-map = f2-vec, except for calling clojure.lang.RT.map / vector. So there are only three versions of the actual bytecode: - the closure f1/f4; - f2 building a new object in its static constructor - f2-nil using a null constant instead of a field containing null. importantly, f1/f4 are identical: public final class F extends clojure.lang.AFunction { /* ... static constructor getting clojure.core/= ... */ Object x; public F(Object o) { x = o } public Object invoke( Object y ) { /*basically*/ return (bool (= x y)) } } So why does f4 behave almost like f2/f3?! Cheers, -- pascal -- 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.