Thanks for reminding me about #1 ;)
On Jan 14, 11:08 pm, Rich Hickey <richhic...@gmail.com> wrote:
> On Jan 14, 2:57 pm, Rich Hickey <richhic...@gmail.com> wrote:
>
>
>
> > On Jan 13, 12:39 pm, samppi <rbysam...@gmail.com> wrote:
>
> > > Recently, I asked how to make a function evaluate its arguments lazily
> > > (http://groups.google.com/group/clojure/browse_thread/thread/
> > > cd01ef39c2b62530), and I was given a good solution: use Delay objects
> > > (with the delay and force functions).
>
> > > I wanted to do this for the efficiency of a functional parser library
> > > that uses many meta-functions and meta-meta-functions: I thought that
> > > stopping arguments from being evaluated until needed was a good way to
> > > prevent useless creation of objects, especially in huge trees of meta-
> > > meta-functions. But I was very surprised when running my library's
> > > unit tests to see that using Delay objects took much more time to run
> > > the tests than not using Delays. Here's an example in a REPL:
>
> > > Clojure
> > > user=> (defn alt [& functions]
> > > (fn [tokens]
> > > (some #(% tokens) functions)))
> > > #'user/alt
> > > user=> (defn sub-function1 [c] (println "1:" c) (fn [c] false))
> > > #'user/sub-function1
> > > user=> (defn sub-function2 [c] (println "2:" c) (fn [c] true))
> > > #'user/sub-function2
> > > user=> (defn sub-function3 [c] (println "3:" c) (fn [c] false))
> > > #'user/sub-function3
> > > user=> (defn a-meta-meta-function [c]
> > > (alt (sub-function1 c) (sub-function2 c) (sub-function3 c)))
> > > #'user/a-meta-meta-function
> > > user=> (time ((a-meta-meta-function "CONTEXT") [:a :b :c]))
> > > 1: CONTEXT
> > > 2: CONTEXT
> > > 3: CONTEXT
> > > "Elapsed time: 1.018 msecs"
> > > true
>
> > > ...vs...
>
> > > Clojure
> > > user=> (defn alt [& functions]
> > > (fn [tokens]
> > > (some #((force %) tokens) functions)))
> > > #'user/alt
> > > user=> (defn sub-function1 [c] (println "1:" c) (delay (fn [c]
> > > false))))
> > > #'user/sub-function1
> > > user=> java.lang.Exception: Unmatched delimiter: )
> > > user=> (defn sub-function1 [c] (println "1:" c) (delay (fn [c]
> > > false)))
> > > #'user/sub-function1
> > > user=> (defn sub-function2 [c] (println "2:" c) (delay (fn [c] true)))
> > > #'user/sub-function2
> > > user=> (defn sub-function3 [c] (println "3:" c) (delay (fn [c]
> > > false)))
> > > #'user/sub-function3
> > > user=> (defn a-meta-meta-function [c]
> > > (alt (sub-function1 c) (sub-function2 c) (sub-function3 c)))
> > > #'user/a-meta-meta-function
> > > user=> (time ((a-meta-meta-function foo) some-tokens))
> > > java.lang.Exception: Unable to resolve symbol: foo in this context
> > > (NO_SOURCE_FILE:13)
> > > user=> (time ((a-meta-meta-function "CONTEXT") [:a :b :c]))
> > > 1: CONTEXT
> > > 2: CONTEXT
> > > 3: CONTEXT
> > > "Elapsed time: 2.443 msecs"
> > > true
>
> > > Why would it take so much more time? Is it because it might take a
> > > long time to construct a Delay object? Can I do something different to
> > > make it more efficient, or should I just not use Delay objects?
>
> > It's hard to enumerate everything that is problematic with this
> > approach to determining efficiency.
>
> > Let's start with the basics:
>
> > 1) Premature optimization is the root of all evil
> > 2) See #1
> > 3) You can't draw conclusions from a single execution of a short
> > function
> > 4) See #1
> > 5) If you design with Delays etc to put off, avoid or cache a time-
> > consuming computation, then test with trivial computations, you know
> > nothing
> > 6) See #1
> > 7) timings that include I/O tend to be dominated by it
> > 8) see #1
> > ...
>
> On rereading this I see #5 could be taken the wrong way - I mean you
> learn nothing from that test, as the Delays/parallelization etc
> dominate the time, when with a long computation they wouldn't.
>
> Rich
--~--~---------~--~----~------------~-------~--~----~
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
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
-~----------~----~----~----~------~----~------~--~---