On Wednesday, November 17, 2010, Sunil S Nandihalli
<sunil.nandiha...@gmail.com> wrote:
> Regarding your bimap implementation, in terms of complexity, I feel, it will 
> be linear in the number of elements, when accessing the pair via the value .. 
> Is that true?

No I use two maps and rmap is O(1) so rmap+get is O(log32 n) like a
direct get. What may confuse you is that only the direct map is
hinted. The reverse map doesn't need to: no interop calls on it while
it is in reverse position.

> On Tue, Nov 16, 2010 at 2:36 PM, Christophe Grand <christo...@cgrand.net> 
> wrote:
>
>
> You can implement your own, prettu easily with deftype.
> However it can be tedious to track every methods, so we need a repl helper 
> function to scaffold the code for us.
>
> (defn scaffold [iface]
>   (doseq [[iface methods] (->> iface .getMethods
>                             (map #(vector (.getName (.getDeclaringClass %))
>                                     (symbol (.getName %))
>                                     (count (.getParameterTypes %))))
>                             (group-by first))]
>     (println (str "  " iface))
>     (doseq [[_ name argcount] methods]
>       (println
>         (str "    "
>           (list name (into ['this] (take argcount (repeatedly gensym)))))))))
>
> user=> (scaffold clojure.lang.IPersistentMap)
>   clojure.lang.IPersistentMap
>     (assoc [this G__441 G__442])
>     (without [this G__443])
>     (assocEx [this G__444 G__445])
>   java.lang.Iterable
>     (iterator [this])
>   clojure.lang.Associative
>     (containsKey [this G__446])
>     (assoc [this G__447 G__448])
>     (entryAt [this G__449])
>   clojure.lang.IPersistentCollection
>     (count [this])
>     (cons [this G__450])
>     (empty [this])
>     (equiv [this G__451])
>   clojure.lang.Seqable
>     (seq [this])
>   clojure.lang.ILookup
>     (valAt [this G__452 G__453])
>     (valAt [this G__454])
>   clojure.lang.Counted
>     (count [this])
> nil
>
> Now you need to remove the duplicates (count and assoc), wrap everything in a 
> deftype form and implement it:
> (including a new protocol fn to reverse a bidi map)
>
> (defprotocol ReversibleMap
>   (rmap [m]))
>
> (defn- rdissoc [d r v]
>  (if-let [[_ k] (find r v)] (dissoc d k) d))
>
> (deftype Bimap [^clojure.lang.IPersistentMap direct reverse]
>   Object
>   (hashCode [x]
>     (.hashCode direct))
>   (equals [x y]
>     (.equals direct y))
>   clojure.lang.IPersistentMap
>     (without [this k]
>       (Bimap.
>         (dissoc direct k)
>         (rdissoc reverse direct k)))
>     (assocEx [this k v]
>       (if (or (contains? direct k) (contains? reverse v))
>         (throw (Exception. "Key or value already present"))
>         (assoc this k v)))
>   java.lang.Iterable
>     (iterator [this]
>       (.iterator direct))
>   clojure.lang.Associative
>     (assoc [this k v]
>       (Bimap.
>         (assoc (rdissoc direct reverse v) k v)
>         (assoc (rdissoc reverse direct k) v k)))
>     (containsKey [this k]
>       (contains? direct k))
>     (entryAt [this k]
>       (find direct k))
>   clojure.lang.IPersistentCollection
>     (cons [this x]
>       (if-let [[k v] (and (vector? x) x)]
>         (assoc this k v)
>         (reduce (fn [m [k v]] (assoc m k v)) this x)))
>     (empty [this]
>       (.empty direct))
>     (equiv [this x]
>       (.equiv direct x))
>   clojure.lang.Seqable
>     (seq [this]
>       (seq direct))
>   clojure.lang.ILookup
>     (valAt [this k else]
>       (direct k else))
>     (valAt [this k]
>       (direct k))
>   clojure.lang.Counted
>     (count [this]
>       (count direct))
>   ReversibleMap
>     (rmap [this]
>       (Bimap. reverse direct)))
>
> (defn bimap [& kvs]
>   (reduce (fn [m [k v]] (assoc m k v)) (Bimap. {} {}) (partition 2 kvs)))
>
> Some quick tests:
> user=> (assoc (bimap :a 1 :b 2) [:c 3] [:d 4] [:e 5])
> {[:e 5] nil, [:c 3] [:d 4], :b 2, :a 1}
> user=> (assoc (bimap :a 1 :b 2) :c 3 :d 4 :e 5)
> {:e 5, :d 4, :c 3, :b 2, :a 1}
> user=> (assoc (bimap :a 1 :b 2) :c 3 :d 2 :e 5)
> {:e 5, :d 2, :c 3, :a 1}
> user=> (dissoc *1 :d)
> {:e 5, :c 3, :a 1}
> user=> (rmap *1)
> {5 :e, 3 :c, 1 :a}
> user=> (assoc *1 2 :c)
> {2 :c, 5 :e, 1 :a}
>
> hth,
>
> Christophe
>
>
>
>
>
> On Tue, Nov 16, 2010 at 8:16 AM, Sunil S Nandihalli 
> <sunil.nandiha...@gmail.com> wrote:
>
>
>
> A bimap is a map where each elements of the pair can be used as key to access 
> it..
> Sunil.
>
> On Tue, Nov 16, 2010 at 12:44 PM, Sunil S Nandihalli 
> <sunil.nandiha...@gmail.com> wrote:

-- 
Professional: http://cgrand.net/ (fr)
On Clojure: http://clj-me.cgrand.net/ (en)

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to