diff options
author | Timothy Pratley <timothypratley@gmail.com> | 2010-01-30 15:08:09 +1100 |
---|---|---|
committer | Stuart Halloway <stu@thinkrelevance.com> | 2010-06-07 10:03:40 -0400 |
commit | 24442426af1fe643d904b4adfcf62fd7a1cf3ff7 (patch) | |
tree | 524a9c14019b1d311bc235c1b4545e8571a488cb | |
parent | eb4502cb1e9cbc7a9a9378af1f8b8c1cd8cc6507 (diff) |
added fnil to supply default values #257
Signed-off-by: Stuart Halloway <stu@thinkrelevance.com>
-rw-r--r-- | src/clj/clojure/core.clj | 23 | ||||
-rw-r--r-- | test/clojure/test_clojure/other_functions.clj | 11 |
2 files changed, 34 insertions, 0 deletions
diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj index 017b0b70..22357b69 100644 --- a/src/clj/clojure/core.clj +++ b/src/clj/clojure/core.clj @@ -5669,6 +5669,29 @@ (cons x (keepi (inc idx) (rest s)))))))))] (keepi 0 coll)))) +(defn fnil + "Takes a function f, and returns a function that calls f, replacing + a nil first argument to f with the supplied value x. Higher arity + versions can replace arguments in the second and third + positions (y, z). Note that the function f can take any number of + arguments, not just the one(s) being nil-patched." + ([f x] + (fn + ([a] (f (if (nil? a) x a))) + ([a b] (f (if (nil? a) x a) b)) + ([a b c] (f (if (nil? a) x a) b c)) + ([a b c & ds] (apply f (if (nil? a) x a) b c ds)))) + ([f x y] + (fn + ([a b] (f (if (nil? a) x a) (if (nil? b) y b))) + ([a b c] (f (if (nil? a) x a) (if (nil? b) y b) c)) + ([a b c & ds] (apply f (if (nil? a) x a) (if (nil? b) y b) c ds)))) + ([f x y z] + (fn + ([a b] (f (if (nil? a) x a) (if (nil? b) y b))) + ([a b c] (f (if (nil? a) x a) (if (nil? b) y b) (if (nil? c) z c))) + ([a b c & ds] (apply f (if (nil? a) x a) (if (nil? b) y b) (if (nil? c) z c) ds))))) + (defn- ^{:dynamic true} assert-valid-fdecl "A good fdecl looks like (([a] ...) ([a b] ...)) near the end of defn." [fdecl] diff --git a/test/clojure/test_clojure/other_functions.clj b/test/clojure/test_clojure/other_functions.clj index 575ac9fb..afb67631 100644 --- a/test/clojure/test_clojure/other_functions.clj +++ b/test/clojure/test_clojure/other_functions.clj @@ -50,6 +50,17 @@ "bar" 'bar "quux" "quux")) +(deftest test-fnil + (are [x y] (= x y) + ((fnil + 0) nil 42) 42 + ((fnil conj []) nil 42) [42] + (reduce #(update-in %1 [%2] (fnil inc 0)) {} + ["fun" "counting" "words" "fun"]) + {"words" 1, "counting" 1, "fun" 2} + (reduce #(update-in %1 [(first %2)] (fnil conj []) (second %2)) {} + [[:a 1] [:a 2] [:b 3]]) + {:b [3], :a [1 2]})) + ; time assert comment doc ; partial |