Mercurial > rlm
view src/rlm/function_utils.clj @ 1:8565803376a4
upgrading source to work with clojure 1.4
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Tue, 28 Feb 2012 13:26:34 -0600 |
parents | 78a630e650d2 |
children | b8bbb0dbda7b |
line wrap: on
line source
1 ;; Various Operators on Pure Functions2 ;;3 ;; Open source Liscence and all that4 (ns5 rlm.function-utils6 "Collection of Operators on Pure Functions"7 {:author "Robert McIntyre"})9 (def void ::void)11 (defn mix12 "Takes any number of mathematically equal functions with13 possibly different run-times and returns a function that14 runs each in a separate thread, returns the result from15 the first thread which finishes, and cancels the other threads."16 {:author "Robert McIntyre"}17 ([& functions]18 (fn [& args]19 (let [result (promise)20 futures (doall (for [fun functions]21 (future (deliver result (apply fun args)))))22 answer @result]23 (dorun (map future-cancel futures))24 answer))))26 ;; (defn mix-threads27 ;; " Takes any number of pure functions that take the same arguments and28 ;; compute the same value and returns a function that runs each in a separate29 ;; thread, returns the result from the first thread which finshes, and cancels30 ;; the other threads. Explicitly uses nasty Threads.32 ;; For example:33 ;; (do34 ;; (defn fun1 [] (Thread/sleep 5000) 5)35 ;; (defn fun2 [] (Thread/sleep 700000) 5)36 ;; (time ((mix fun1 fun2))))38 ;; Returns:39 ;; | Elapsed time: 5000.66214 msecs40 ;; 5"41 ;; [& functions]42 ;; (fn [& args]43 ;; (let [result (prof :create-atom (atom void))44 ;; threads45 ;; (prof :create-threads (map46 ;; (fn [fun]47 ;; (Thread.48 ;; (fn []49 ;; (try (let [answer (apply fun args)]50 ;; (reset! result answer))51 ;; (catch Exception _ nil)))))52 ;; functions))]54 ;; (prof :start-threads (dorun (map #(.start %) threads)))55 ;; (prof :loop (loop []56 ;; (if (= (deref result) void)57 ;; (recur)58 ;; (do (prof :kill-threads (dorun (map #(.stop %) threads)))59 ;; (prof :return (deref result)))))))))61 (defmacro defmix62 " Defines a function from any number of pure functions that take the same63 arguments and compute the same value which:65 Runs each in a separate thread.66 Returns the result from the first thread which finshes.67 Cancels the other threads.69 Use this whenever you want to combine two pure functions that70 compute the same thing, but use different algorithms with different71 run times for various inputs.73 For example:74 (do75 (defn fun1 [] (Thread/sleep 5000) 5)76 (defn fun2 [] (Thread/sleep 700000) 5)77 (defmix fun3 \"combination of fun1 and fun2\" fun1 fun2)78 (time (fun3))80 Returns:81 | Elapsed time: 5000.66214 msecs82 5"84 {:arglists '([name doc-string? functions*])}86 [name & functions]87 (let [doc-string (if (string? (first functions)) (first functions) "")88 functions (if (string? (first functions)) (rest functions) functions)89 arglists (:arglists (meta (resolve (eval `(quote ~(first functions))))))90 name (with-meta name91 (assoc (meta name) :arglists `(quote ~arglists)92 :doc doc-string))]93 `(def ~name (mix ~@functions))))95 (defn runonce96 "Decorator. returns a function which will run only once. Inspired97 by Halloway's version from lancet."98 {:author "Robert McIntyre"}99 [function]100 (let [sentinel (Object.)101 result (atom sentinel)]102 (fn [& args]103 (locking sentinel104 (if (= @result sentinel)105 (reset! result (apply function args))106 @result)))))