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"