Mercurial > rlm
diff src/rlm/function_utils.clj @ 6:b8bbb0dbda7b
merging
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Thu, 01 Mar 2012 05:55:59 -0700 |
parents | 12d1367cf1aa 8565803376a4 |
children | 1065e7d615a4 |
line wrap: on
line diff
1.1 --- a/src/rlm/function_utils.clj Thu Mar 01 05:47:37 2012 -0700 1.2 +++ b/src/rlm/function_utils.clj Thu Mar 01 05:55:59 2012 -0700 1.3 @@ -4,68 +4,11 @@ 1.4 (ns 1.5 rlm.function-utils 1.6 "Collection of Operators on Pure Functions" 1.7 - {:author "Robert McIntyre"} 1.8 - (:use [clojure.contrib.profile])) 1.9 + {:author "Robert McIntyre"}) 1.10 1.11 (def void ::void) 1.12 1.13 -(comment 1.14 - 1.15 - "Please help me out here. I'm trying to make a higher order function that takes 1.16 - pure functions that are mathmaticaly the same but have different times and returns another 1.17 - function that runs them both and returns the resut of the one that finishes first." 1.18 - 1.19 - 1.20 - "here's a repl session: 1.21 - 1.22 -mobius> " (time (dotimes [_ 500]((mix-futures + +) 40 3 3 3 3 3))) " 1.23 -Elapsed time: 85.792995 msecs 1.24 -nil 1.25 -mobius> " (time (dotimes [_ 500](+ 40 3 3 3 3 3))) " 1.26 -Elapsed time: 6.956338 msecs 1.27 -nil 1.28 -mobius> " (time (dotimes [_ 500]((mix-threads + +) 40 3 3 3 3 3))) " 1.29 -Elapsed time: 706.227065 msecs 1.30 -nil 1.31 - 1.32 - 1.33 -mobius> " (defn fast-five [& args] 5) " 1.34 -#'mobius/fast-five 1.35 - 1.36 -mobius> " (defn slow-five [& args] (Thread/sleep 5000) (println "Oh YEAH!!!!") 5) " 1.37 -#'mobius/slow-five 1.38 - 1.39 -mobius> " (profile (time (dotimes [_ 5000] (thread-five)))) " 1.40 -\"Elapsed time: 12187.981587 msecs\" 1.41 - Name mean min max count sum 1.42 - create-atom 9621 2025 4433928 5000 48106830 1.43 -create-threads 5156 2724 2880268 5000 25783796 1.44 - kill-threads 91313 27866 11175718 5000 456567066 1.45 - loop 2124249 38482 18470781 5000 10621249899 1.46 - return 1242 838 5309 5000 6212626 1.47 - start-threads 252985 110348 12272835 5000 1264927953 1.48 -nil 1.49 - 1.50 -mobius> " (profile (time (dotimes [_ 5000] (future-five)))) " 1.51 -\"Elapsed time: 607.266671 msecs\" 1.52 - Name mean min max count sum 1.53 - create-atom 1472 1047 31708 5000 7363139 1.54 -create-futures 30539 2514 1330660 5000 152697998 1.55 - kill-threads 54158 2444 3938833 5000 270792897 1.56 - loop 81117 8800 6083059 5000 405587516 1.57 - return 1215 838 618782 5000 6078146 1.58 -nil 1.59 - 1.60 - 1.61 - 1.62 -What can I improve here, and why is the future version sooo much faster than the 1.63 -thread version? Is there a better way than using loop? 1.64 -" 1.65 - 1.66 -) 1.67 - 1.68 - 1.69 -(defn race 1.70 +(defn race 1.71 "Takes any number of mathematically equal functions with 1.72 possibly different run-times and returns a function that 1.73 runs each in a separate thread, returns the result from 1.74 @@ -108,44 +51,6 @@ 1.75 (dorun (map future-cancel futures)) 1.76 answer)))) 1.77 1.78 - 1.79 - 1.80 -(defn mix-threads 1.81 - " Takes any number of pure functions that take the same arguments and 1.82 - compute the same value and returns a function that runs each in a separate 1.83 - thread, returns the result from the first thread which finshes, and cancels 1.84 - the other threads. Explicitly uses nasty Threads. 1.85 - 1.86 - For example: 1.87 - (do 1.88 - (defn fun1 [] (Thread/sleep 5000) 5) 1.89 - (defn fun2 [] (Thread/sleep 700000) 5) 1.90 - (time ((mix fun1 fun2)))) 1.91 - 1.92 - Returns: 1.93 - | Elapsed time: 5000.66214 msecs 1.94 - 5" 1.95 - [& functions] 1.96 - (fn [& args] 1.97 - (let [result (prof :create-atom (atom void)) 1.98 - threads 1.99 - (prof :create-threads (map 1.100 - (fn [fun] 1.101 - (Thread. 1.102 - (fn [] 1.103 - (try (let [answer (apply fun args)] 1.104 - (reset! result answer)) 1.105 - (catch Exception _ nil))))) 1.106 - functions))] 1.107 - 1.108 - (prof :start-threads (dorun (map #(.start %) threads))) 1.109 - (prof :loop (loop [] 1.110 - (if (= (deref result) void) 1.111 - (recur) 1.112 - (do (prof :kill-threads (dorun (map #(.stop %) threads))) 1.113 - (prof :return (deref result))) 1.114 - )))))) 1.115 - 1.116 (defmacro defmix 1.117 " Defines a function from any number of pure functions that take the same 1.118 arguments and compute the same value which: 1.119 @@ -175,10 +80,11 @@ 1.120 (let [doc-string (if (string? (first functions)) (first functions) "") 1.121 functions (if (string? (first functions)) (rest functions) functions) 1.122 arglists (:arglists (meta (resolve (eval `(quote ~(first functions)))))) 1.123 - name (with-meta name (assoc (meta name) :arglists `(quote ~arglists) :doc doc-string))] 1.124 + name (with-meta name 1.125 + (assoc (meta name) :arglists `(quote ~arglists) 1.126 + :doc doc-string))] 1.127 `(def ~name (mix ~@functions)))) 1.128 1.129 - 1.130 (defn runonce 1.131 "Decorator. returns a function which will run only once. Inspired 1.132 by Halloway's version from lancet." 1.133 @@ -192,21 +98,3 @@ 1.134 (reset! result (apply function args)) 1.135 @result))))) 1.136 1.137 - 1.138 - 1.139 -;I'm thinking this will be the docstring for mix eventually. 1.140 - 1.141 - ;; " Takes any number of pure functions that take the same arguments and 1.142 - ;; compute the same value and returns a function that runs each in a separate 1.143 - ;; thread, returns the result from the first thread which finshes, and cancels 1.144 - ;; the other threads. 1.145 - 1.146 - ;; For example: 1.147 - ;; (do 1.148 - ;; (defn fun1 [] (Thread/sleep 5000) 5) 1.149 - ;; (defn fun2 [] (Thread/sleep 700000) 5) 1.150 - ;; (time ((mix fun1 fun2)))) 1.151 - 1.152 - ;; Returns: 1.153 - ;; | Elapsed time: 5000.66214 msecs 1.154 - ;; 5"