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? --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---