Permalink
Browse files

Migrated generic.functor

  • Loading branch information...
1 parent 2143dd1 commit 1381315259c3c5ca8b8deec9e094bcf70742fbb9 @khinsen khinsen committed Oct 8, 2011
View
39 src/main/clojure/clojure/algo/generic/functor.clj
@@ -0,0 +1,39 @@
+;; Generic interface for functors
+
+;; by Konrad Hinsen
+
+;; Copyright (c) Konrad Hinsen, 2009-2011. All rights reserved. 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
+ ^{:author "Konrad Hinsen"
+ :doc "Generic functor interface (fmap)"}
+ clojure.algo.generic.functor)
+
+
+(defmulti fmap
+ "Applies function f to each item in the data structure s and returns
+ a structure of the same kind."
+ {:arglists '([f s])}
+ (fn [f s] (type s)))
+
+(defmethod fmap clojure.lang.IPersistentList
+ [f v]
+ (map f v))
+
+(defmethod fmap clojure.lang.IPersistentVector
+ [f v]
+ (into (empty v) (map f v)))
+
+(defmethod fmap clojure.lang.IPersistentMap
+ [f m]
+ (into (empty m) (for [[k v] m] [k (f v)])))
+
+(defmethod fmap clojure.lang.IPersistentSet
+ [f s]
+ (into (empty s) (map f s)))
View
57 src/test/clojure/clojure/algo/generic/test_functor.clj
@@ -0,0 +1,57 @@
+;; Test routines for clojure.algo.generic.collection
+
+;; Copyright (c) Konrad Hinsen, 2011. All rights reserved. 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 clojure.algo.generic.test-functor
+ (:use [clojure.test :only (deftest is are run-tests)])
+ (:require [clojure.algo.generic.functor :as gf])
+ (:require [clojure.algo.generic.collection :as gc]))
+
+; Test implementations for CLojure's built-in collections
+(deftest builtin-collections
+ (are [a b] (= a b)
+ (gf/fmap inc (list 1 2 3)) (list 2 3 4)
+ (gf/fmap inc [1 2 3]) [2 3 4]
+ (gf/fmap inc {:A 1 :B 2 :C 3}) {:A 2 :B 3 :C 4}
+ (gf/fmap inc #{1 2 3}) #{2 3 4}))
+
+
+; Define a multiset class. The representation is a map from values to counts.
+(defrecord multiset [map])
+
+(defn mset
+ [& elements]
+ (gc/into (new multiset {}) elements))
+
+; Implement the collection multimethods.
+(defmethod gc/conj multiset
+ ([ms x]
+ (let [msmap (:map ms)]
+ (new multiset (assoc msmap x (inc (get msmap x 0))))))
+ ([ms x & xs]
+ (reduce gc/conj (gc/conj ms x) xs)))
+
+(defmethod gc/empty multiset
+ [ms]
+ (new multiset {}))
+
+(defmethod gc/seq multiset
+ [ms]
+ (apply concat (map (fn [[x n]] (repeat n x)) (:map ms))))
+
+; Implement fmap
+(defmethod gf/fmap multiset
+ [f m]
+ (gc/into (gc/empty m) (map f (gc/seq m))))
+
+; Multiset tests
+(deftest multiset-tests
+ (are [a b] (= a b)
+ (gf/fmap inc (mset 1 2 3)) (mset 2 3 4)))
+

0 comments on commit 1381315

Please sign in to comment.