diff --git a/src/flatland/useful/fn.clj b/src/flatland/useful/fn.clj index 269898f..13f1116 100644 --- a/src/flatland/useful/fn.clj +++ b/src/flatland/useful/fn.clj @@ -169,3 +169,33 @@ (if (= args (get cache :args ::not-found)) cache {:args args, :value (apply f args)}))))))) + +(defprotocol EquivChecker + "Given an object, produce a function for quickly testing equality with that object." + (=? [x] "Return a function of y which computes (= x y).")) + +(let [identity-checker {:=? (fn [x] + (fn [y] + (identical? x y)))} + equals-checker {:=? (fn [^Object x] + (fn [^Object y] + (.equals x y)))}] + (extend nil + EquivChecker identity-checker) + (extend clojure.lang.Keyword + EquivChecker identity-checker) + (extend clojure.lang.Symbol + EquivChecker equals-checker) + (extend String + EquivChecker equals-checker)) + +(extend-protocol EquivChecker + Number + (=? [x] + (fn [y] + (and (instance? Number y) + (clojure.lang.Numbers/equal x y)))) + Object + (=? [x] + (fn [y] + (= x y)))) diff --git a/test/flatland/useful/fn_test.clj b/test/flatland/useful/fn_test.clj index c08e2f6..ff87232 100644 --- a/test/flatland/useful/fn_test.clj +++ b/test/flatland/useful/fn_test.clj @@ -79,3 +79,13 @@ (deftest test-ignoring-nils (is (= 6 ((ignoring-nils +) 1 nil 2 nil nil 3)))) + +(deftest test-=? + (let [objs [1 :x [2] "foo"]] + (doseq [i (range (count objs)) + :let [x (objs i) + f (=? x)] + j (range (count objs)) + :let [y (objs j)]] + (is (= (boolean (f y)) + (boolean (= i j)))))))