diff --git a/src/monger/internal/fn.clj b/src/monger/internal/fn.clj new file mode 100644 index 0000000..a6e55d6 --- /dev/null +++ b/src/monger/internal/fn.clj @@ -0,0 +1,59 @@ +;; Copyright (c) 2011-2012 Michael S. Klishin +;; +;; The use and distribution terms for this software are covered by the +;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) +;; which can be found in the file epl-v10.html at the root of this distribution. +;; By using this software in any fashion, you are agreeing to be bound by +;; the terms of this license. +;; You must not remove this notice, or any other, from this software. + +(ns monger.internal.fn) + + +;; +;; Implementation +;; + +(defn- apply-to-values [m f] + "Applies function f to all values in map m" + (into {} (for [[k v] m] + [k (f v)]))) + + +;; +;; API +;; + +(defprotocol IFNExpansion + (expand-all [x] "Invokes functions, recursively expands maps, evaluates all other values to themselves")) + +(extend-protocol IFNExpansion + java.lang.Integer + (expand-all [i] i) + + java.lang.Long + (expand-all [l] l) + + java.lang.String + (expand-all [s] s) + + java.lang.Float + (expand-all [f] f) + + java.lang.Double + (expand-all [d] d) + + java.util.Map + (expand-all [m] (apply-to-values m expand-all)) + + clojure.lang.PersistentVector + (expand-all [v] v) + + clojure.lang.APersistentMap + (expand-all [m] (apply-to-values m expand-all)) + + clojure.lang.IFn + (expand-all [f] (f)) + + Object + (expand-all [x] x)) diff --git a/test/monger/test/internal/fn.clj b/test/monger/test/internal/fn.clj new file mode 100644 index 0000000..f76d210 --- /dev/null +++ b/test/monger/test/internal/fn.clj @@ -0,0 +1,36 @@ +(ns monger.test.internal.fn + (:use [clojure.test] + [monger.internal.fn])) + + +(deftest test-recursive-function-values-expansion + (are [i o] (is (= (expand-all i) o)) + { :int (fn [] 1) :str "Clojure" :float (Float/valueOf 11.0) } { :int 1 :str "Clojure" :float (Float/valueOf 11.0 )} + { :long (fn [] (Long/valueOf 11)) } { :long (Long/valueOf 11) } + { + :i 1 + :l (Long/valueOf 1111) + :s "Clojure" + :d (Double/valueOf 11.1) + :f (Float/valueOf 2.5) + :v [1 2 3] + :dyn-i (fn [] 1) + :dyn-s (fn [] "Clojure (expanded)") + :m { :nested "String" } + :dyn-m { :abc (fn [] :abc) :nested { :a { :b { :c (fn [] "d") } } } } + } + { + :i 1 + :l (Long/valueOf 1111) + :s "Clojure" + :d (Double/valueOf 11.1) + :f (Float/valueOf 2.5) + :v [1 2 3] + :dyn-i 1 + :dyn-s "Clojure (expanded)" + :m { :nested "String" } + :dyn-m { + :abc :abc + :nested { :a { :b { :c "d" } } } + } + }))