Created
September 15, 2010 09:08
-
-
Save grinnbearit/580454 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;;; Internally defining MultiMap fails on compilation with the error | |
;;; | |
;;; error: java.lang.VerifyError: (class: multi-map/PersistentMultiMap, method: equiv signature: | |
;;; (Ljava/lang/Object;)Z) Expecting to find integer on stack (multi_map.clj:0) | |
;;; | |
(ns multi-map | |
(:refer-clojure :exclude [count assoc empty cons seq]) | |
(:require [clojure.set :as set]) | |
(:import clojure.lang.MapEntry java.util.Map)) | |
(declare mm-str mm-get mm-count mm-assoc mm-empty mm-conj mm-equiv mm-contains? mm-entryAt mm-seq mm-dissoc mm-empty? | |
mm-seq-pairs mm-conj-swap mm-assoc-swap mm-dissoc-one mm-containsValue mm-keys mm-vals mm-entrySet) | |
(defprotocol MultiMap | |
(count [this]) | |
(assoc [this key val]) | |
(empty [this]) | |
(cons [this e]) | |
(equiv [this o]) | |
(containsKey [this key]) | |
(entryAt [this key]) | |
(seq [this]) | |
(without [this key]) | |
(seq-pairs [this]) | |
(conj-swap [this key-coll] [this key-coll & key-colls]) | |
(assoc-swap [this key coll] [this key coll & key-colls]) | |
(dissoc-one [this key val] [this key val & kvs])) | |
(deftype PersistentMultiMap [key->vals __meta] | |
Object | |
(toString [this] (mm-str this)) | |
clojure.lang.ILookup | |
(valAt [this key] (mm-get this key)) | |
(valAt [this key not-found] (mm-get this key not-found)) | |
clojure.lang.IPersistentMap | |
(count [this] (mm-count this)) | |
(assoc [this key val] (mm-assoc this key val)) | |
(empty [this] mm-empty) | |
(cons [this e] (mm-conj this e)) | |
(equiv [this o] (mm-equiv this o)) | |
(containsKey [this key] (mm-contains? this key)) | |
(entryAt [this key] (mm-entryAt this key)) | |
(seq [this] (mm-seq this)) | |
(without [this key] (mm-dissoc this key)) | |
java.io.Serializable | |
Map | |
(size [this] (mm-count this)) | |
(isEmpty [this] (mm-empty? this)) | |
(containsValue [this v] (mm-containsValue this v)) | |
(get [this k] (mm-get this k)) | |
(put [this k v] (throw (UnsupportedOperationException.))) | |
(remove [this k] (throw (UnsupportedOperationException.))) | |
(putAll [this m] (throw (UnsupportedOperationException.))) | |
(clear [this] (throw (UnsupportedOperationException.))) | |
(keySet [this] (mm-keys this)) | |
(values [this] (mm-vals this)) | |
(entrySet [this] (mm-entrySet this)) | |
MultiMap | |
(seq-pairs [this] (mm-seq-pairs this)) | |
(conj-swap [this key-coll] (mm-conj-swap this key-coll)) | |
(conj-swap [this key-coll & key-colls] (mm-conj-swap this key-coll key-colls)) | |
(assoc-swap [this key coll] (mm-assoc-swap this key coll)) | |
(assoc-swap [this key coll & key-colls] (mm-assoc-swap this key coll key-colls)) | |
(dissoc-one [this key val] (mm-dissoc-one this key val)) | |
(dissoc-one [this key val & kvs] (mm-dissoc-one this key val kvs)) | |
clojure.lang.IFn | |
(invoke [this k] (mm-get this k)) | |
(invoke [this k not-found] (mm-get this k not-found)) | |
clojure.lang.IObj | |
(meta [this] __meta) | |
(withMeta [this m] (PersistentMultiMap. key->vals m))) | |
(defn- ^:static mm-str [^PersistentMultiMap mm] | |
(str (.key->vals mm))) | |
(defn- mm-get | |
(^:static [^PersistentMultiMap mm key] | |
(mm-get mm key nil)) | |
(^:static [^PersistentMultiMap mm key not-found] | |
(get (.key->vals mm) key not-found))) | |
(defn- mm-count [^PersistentMultiMap mm] | |
(clojure.core/count (.key->vals mm))) | |
(defn- mm-assoc [^PersistentMultiMap mm key val] | |
(let [key->vals (.key->vals mm)] | |
(if-let [s (get key->vals key nil)] | |
(PersistentMultiMap. (clojure.core/assoc key->vals key (conj s val))) | |
(PersistentMultiMap. (clojure.core/assoc key->vals key #{val}))))) | |
(def ^:private mm-empty | |
(PersistentMultiMap. {} {})) | |
(defn- ^:static mm-conj [^PersistentMultiMap mm [key val]] | |
(mm-assoc mm key val)) | |
(defn- ^:static mm-equiv [^PersistentMultiMap mm o] | |
(= (.key->vals mm) o)) | |
(defn- ^:static mm-contains? [^PersistentMultiMap mm key] | |
(contains? (.key->vals mm) key)) | |
(defn- ^:static mm-entryAt [^PersistentMultiMap mm key] | |
(if-let [v (mm-get mm key)] | |
(MapEntry. key v) | |
nil)) | |
(defn- ^:static mm-seq [^PersistentMultiMap mm] | |
(clojure.core/seq (.key->vals mm))) | |
(defn- ^:static mm-dissoc [^PersistentMultiMap mm key] | |
(let [key->vals (.key->vals mm)] | |
(PersistentMultiMap. (dissoc key->vals key)))) | |
(defn- ^:static mm-empty? [^PersistentMultiMap mm key] | |
(empty? (.key->vals mm))) | |
(defn- ^:static mm-containsValue [^PersistentMultiMap mm v] | |
(some #{v} (apply concat (vals (.key->vals mm))))) | |
(defn- ^:static mm-keys [^PersistentMultiMap mm] | |
(keys (.key->vals mm))) | |
(defn- ^:static mm-vals [^PersistentMultiMap mm] | |
(apply set/union (vals (.key->vals mm)))) | |
(defn- ^:static mm-entrySet [^PersistentMultiMap mm] | |
(set (.key->vals mm))) | |
(defn- ^:static mm-seq-pairs [^PersistentMultiMap mm] | |
(mapcat (fn [[k s]] (map #(MapEntry. k %) s)) | |
(clojure.core/seq (.key->vals mm)))) | |
(defn- mm-conj-swap | |
(^:static [^PersistentMultiMap mm kvs] | |
(conj (.key->vals mm) kvs)) | |
(^:static [^PersistentMultiMap mm kvs & kvss] | |
(apply conj (.key->vals mm) kvs kvss))) | |
(defn- mm-assoc-swap | |
(^:static [^PersistentMultiMap mm [key coll]] | |
(clojure.core/assoc (.key->vals mm) key (set coll))) | |
(^:static [^PersistentMultiMap mm key coll & key-colls] | |
(apply clojure.core/assoc (.key->vals mm) key (set coll) | |
(map (fn [[k c]] (MapEntry. k (set c))) (partition 2 key-colls))))) | |
(defn multi-map [& keyvals] | |
(into mm-empty (partition 2 keyvals))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;;; extend-type works fine | |
;;; | |
(ns multi-map | |
(:refer-clojure :exclude [count assoc empty cons seq]) | |
(:require [clojure.set :as set]) | |
(:import clojure.lang.MapEntry java.util.Map)) | |
(declare mm-str mm-get mm-count mm-assoc mm-empty mm-conj mm-equiv mm-contains? mm-entryAt mm-seq mm-dissoc mm-empty? | |
mm-seq-pairs mm-conj-swap mm-assoc-swap mm-dissoc-one mm-containsValue mm-keys mm-vals mm-entrySet) | |
(defprotocol MultiMap | |
(count [this]) | |
(assoc [this key val]) | |
(empty [this]) | |
(cons [this e]) | |
(equiv [this o]) | |
(containsKey [this key]) | |
(entryAt [this key]) | |
(seq [this]) | |
(without [this key]) | |
(seq-pairs [this]) | |
(conj-swap [this key-coll] [this key-coll & key-colls]) | |
(assoc-swap [this key coll] [this key coll & key-colls]) | |
(dissoc-one [this key val] [this key val & kvs])) | |
(deftype PersistentMultiMap [key->vals __meta] | |
Object | |
(toString [this] (mm-str this)) | |
clojure.lang.ILookup | |
(valAt [this key] (mm-get this key)) | |
(valAt [this key not-found] (mm-get this key not-found)) | |
clojure.lang.IPersistentMap | |
(count [this] (mm-count this)) | |
(assoc [this key val] (mm-assoc this key val)) | |
(empty [this] mm-empty) | |
(cons [this e] (mm-conj this e)) | |
(equiv [this o] (mm-equiv this o)) | |
(containsKey [this key] (mm-contains? this key)) | |
(entryAt [this key] (mm-entryAt this key)) | |
(seq [this] (mm-seq this)) | |
(without [this key] (mm-dissoc this key)) | |
java.io.Serializable | |
Map | |
(size [this] (mm-count this)) | |
(isEmpty [this] (mm-empty? this)) | |
(containsValue [this v] (mm-containsValue this v)) | |
(get [this k] (mm-get this k)) | |
(put [this k v] (throw (UnsupportedOperationException.))) | |
(remove [this k] (throw (UnsupportedOperationException.))) | |
(putAll [this m] (throw (UnsupportedOperationException.))) | |
(clear [this] (throw (UnsupportedOperationException.))) | |
(keySet [this] (mm-keys this)) | |
(values [this] (mm-vals this)) | |
(entrySet [this] (mm-entrySet this)) | |
clojure.lang.IFn | |
(invoke [this k] (mm-get this k)) | |
(invoke [this k not-found] (mm-get this k not-found)) | |
clojure.lang.IObj | |
(meta [this] __meta) | |
(withMeta [this m] (PersistentMultiMap. key->vals m))) | |
(extend-type PersistentMultiMap | |
MultiMap | |
(seq-pairs [this] (mm-seq-pairs this)) | |
(conj-swap [this key-coll] (mm-conj-swap this key-coll)) | |
(conj-swap [this key-coll & key-colls] (mm-conj-swap this key-coll key-colls)) | |
(assoc-swap [this key coll] (mm-assoc-swap this key coll)) | |
(assoc-swap [this key coll & key-colls] (mm-assoc-swap this key coll key-colls )) | |
(dissoc-one [this key val] (mm-dissoc-one this key val)) | |
(dissoc-one [this key val & kvs] (mm-dissoc-one this key val kvs))) | |
(defn- ^:static mm-str [^PersistentMultiMap mm] | |
(str (.key->vals mm))) | |
(defn- mm-get | |
(^:static [^PersistentMultiMap mm key] | |
(mm-get mm key nil)) | |
(^:static [^PersistentMultiMap mm key not-found] | |
(get (.key->vals mm) key not-found))) | |
(defn- mm-count [^PersistentMultiMap mm] | |
(clojure.core/count (.key->vals mm))) | |
(defn- mm-assoc [^PersistentMultiMap mm key val] | |
(let [key->vals (.key->vals mm)] | |
(if-let [s (get key->vals key nil)] | |
(PersistentMultiMap. (clojure.core/assoc key->vals key (conj s val))) | |
(PersistentMultiMap. (clojure.core/assoc key->vals key #{val}))))) | |
(def ^:private mm-empty | |
(PersistentMultiMap. {} {})) | |
(defn- ^:static mm-conj [^PersistentMultiMap mm [key val]] | |
(mm-assoc mm key val)) | |
(defn- ^:static mm-equiv [^PersistentMultiMap mm o] | |
(= (.key->vals mm) o)) | |
(defn- ^:static mm-contains? [^PersistentMultiMap mm key] | |
(contains? (.key->vals mm) key)) | |
(defn- ^:static mm-entryAt [^PersistentMultiMap mm key] | |
(if-let [v (mm-get mm key)] | |
(MapEntry. key v) | |
nil)) | |
(defn- ^:static mm-seq [^PersistentMultiMap mm] | |
(clojure.core/seq (.key->vals mm))) | |
(defn- ^:static mm-dissoc [^PersistentMultiMap mm key] | |
(let [key->vals (.key->vals mm)] | |
(PersistentMultiMap. (dissoc key->vals key)))) | |
(defn- ^:static mm-empty? [^PersistentMultiMap mm key] | |
(empty? (.key->vals mm))) | |
(defn- ^:static mm-containsValue [^PersistentMultiMap mm v] | |
(some #{v} (apply concat (vals (.key->vals mm))))) | |
(defn- ^:static mm-keys [^PersistentMultiMap mm] | |
(keys (.key->vals mm))) | |
(defn- ^:static mm-vals [^PersistentMultiMap mm] | |
(apply set/union (vals (.key->vals mm)))) | |
(defn- ^:static mm-entrySet [^PersistentMultiMap mm] | |
(set (.key->vals mm))) | |
(defn- ^:static mm-seq-pairs [^PersistentMultiMap mm] | |
(mapcat (fn [[k s]] (map #(MapEntry. k %) s)) | |
(clojure.core/seq (.key->vals mm)))) | |
(defn- mm-conj-swap | |
(^:static [^PersistentMultiMap mm kvs] | |
(conj (.key->vals mm) kvs)) | |
(^:static [^PersistentMultiMap mm kvs & kvss] | |
(apply conj (.key->vals mm) kvs kvss))) | |
(defn- mm-assoc-swap | |
(^:static [^PersistentMultiMap mm [key coll]] | |
(clojure.core/assoc (.key->vals mm) key (set coll))) | |
(^:static [^PersistentMultiMap mm key coll & key-colls] | |
(apply clojure.core/assoc (.key->vals mm) key (set coll) | |
(map (fn [[k c]] (MapEntry. k (set c))) (partition 2 key-colls))))) | |
(defn multi-map [& keyvals] | |
(into mm-empty (partition 2 keyvals))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;;; Internally defining the MultiMap protocol works fine when there is no method clash | |
;;; | |
(ns multi-map | |
(:refer-clojure :exclude [count assoc empty cons seq]) | |
(:require [clojure.set :as set]) | |
(:import clojure.lang.MapEntry java.util.Map)) | |
(declare mm-str mm-get mm-count mm-assoc mm-empty mm-conj mm-equiv mm-contains? mm-entryAt mm-seq mm-dissoc mm-empty? | |
mm-seq-pairs mm-conj-swap mm-assoc-swap mm-dissoc-one mm-containsValue mm-keys mm-vals mm-entrySet) | |
(defprotocol MultiMap | |
(seq-pairs [this]) | |
(conj-swap [this key-coll] [this key-coll & key-colls]) | |
(assoc-swap [this key coll] [this key coll & key-colls]) | |
(dissoc-one [this key val] [this key val & kvs])) | |
(deftype PersistentMultiMap [key->vals __meta] | |
Object | |
(toString [this] (mm-str this)) | |
clojure.lang.ILookup | |
(valAt [this key] (mm-get this key)) | |
(valAt [this key not-found] (mm-get this key not-found)) | |
clojure.lang.IPersistentMap | |
(count [this] (mm-count this)) | |
(assoc [this key val] (mm-assoc this key val)) | |
(empty [this] mm-empty) | |
(cons [this e] (mm-conj this e)) | |
(equiv [this o] (mm-equiv this o)) | |
(containsKey [this key] (mm-contains? this key)) | |
(entryAt [this key] (mm-entryAt this key)) | |
(seq [this] (mm-seq this)) | |
(without [this key] (mm-dissoc this key)) | |
java.io.Serializable | |
Map | |
(size [this] (mm-count this)) | |
(isEmpty [this] (mm-empty? this)) | |
(containsValue [this v] (mm-containsValue this v)) | |
(get [this k] (mm-get this k)) | |
(put [this k v] (throw (UnsupportedOperationException.))) | |
(remove [this k] (throw (UnsupportedOperationException.))) | |
(putAll [this m] (throw (UnsupportedOperationException.))) | |
(clear [this] (throw (UnsupportedOperationException.))) | |
(keySet [this] (mm-keys this)) | |
(values [this] (mm-vals this)) | |
(entrySet [this] (mm-entrySet this)) | |
MultiMap | |
(seq-pairs [this] (mm-seq-pairs this)) | |
(conj-swap [this key-coll] (mm-conj-swap this key-coll)) | |
(conj-swap [this key-coll & key-colls] (mm-conj-swap this key-coll key-colls)) | |
(assoc-swap [this key coll] (mm-assoc-swap this key coll)) | |
(assoc-swap [this key coll & key-colls] (mm-assoc-swap this key coll key-colls)) | |
(dissoc-one [this key val] (mm-dissoc-one this key val)) | |
(dissoc-one [this key val & kvs] (mm-dissoc-one this key val kvs)) | |
clojure.lang.IFn | |
(invoke [this k] (mm-get this k)) | |
(invoke [this k not-found] (mm-get this k not-found)) | |
clojure.lang.IObj | |
(meta [this] __meta) | |
(withMeta [this m] (PersistentMultiMap. key->vals m))) | |
(defn- ^:static mm-str [^PersistentMultiMap mm] | |
(str (.key->vals mm))) | |
(defn- mm-get | |
(^:static [^PersistentMultiMap mm key] | |
(mm-get mm key nil)) | |
(^:static [^PersistentMultiMap mm key not-found] | |
(get (.key->vals mm) key not-found))) | |
(defn- mm-count [^PersistentMultiMap mm] | |
(clojure.core/count (.key->vals mm))) | |
(defn- mm-assoc [^PersistentMultiMap mm key val] | |
(let [key->vals (.key->vals mm)] | |
(if-let [s (get key->vals key nil)] | |
(PersistentMultiMap. (clojure.core/assoc key->vals key (conj s val))) | |
(PersistentMultiMap. (clojure.core/assoc key->vals key #{val}))))) | |
(def ^:private mm-empty | |
(PersistentMultiMap. {} {})) | |
(defn- ^:static mm-conj [^PersistentMultiMap mm [key val]] | |
(mm-assoc mm key val)) | |
(defn- ^:static mm-equiv [^PersistentMultiMap mm o] | |
(= (.key->vals mm) o)) | |
(defn- ^:static mm-contains? [^PersistentMultiMap mm key] | |
(contains? (.key->vals mm) key)) | |
(defn- ^:static mm-entryAt [^PersistentMultiMap mm key] | |
(if-let [v (mm-get mm key)] | |
(MapEntry. key v) | |
nil)) | |
(defn- ^:static mm-seq [^PersistentMultiMap mm] | |
(clojure.core/seq (.key->vals mm))) | |
(defn- ^:static mm-dissoc [^PersistentMultiMap mm key] | |
(let [key->vals (.key->vals mm)] | |
(PersistentMultiMap. (dissoc key->vals key)))) | |
(defn- ^:static mm-empty? [^PersistentMultiMap mm key] | |
(empty? (.key->vals mm))) | |
(defn- ^:static mm-containsValue [^PersistentMultiMap mm v] | |
(some #{v} (apply concat (vals (.key->vals mm))))) | |
(defn- ^:static mm-keys [^PersistentMultiMap mm] | |
(keys (.key->vals mm))) | |
(defn- ^:static mm-vals [^PersistentMultiMap mm] | |
(apply set/union (vals (.key->vals mm)))) | |
(defn- ^:static mm-entrySet [^PersistentMultiMap mm] | |
(set (.key->vals mm))) | |
(defn- ^:static mm-seq-pairs [^PersistentMultiMap mm] | |
(mapcat (fn [[k s]] (map #(MapEntry. k %) s)) | |
(clojure.core/seq (.key->vals mm)))) | |
(defn- mm-conj-swap | |
(^:static [^PersistentMultiMap mm kvs] | |
(conj (.key->vals mm) kvs)) | |
(^:static [^PersistentMultiMap mm kvs & kvss] | |
(apply conj (.key->vals mm) kvs kvss))) | |
(defn- mm-assoc-swap | |
(^:static [^PersistentMultiMap mm [key coll]] | |
(clojure.core/assoc (.key->vals mm) key (set coll))) | |
(^:static [^PersistentMultiMap mm key coll & key-colls] | |
(apply clojure.core/assoc (.key->vals mm) key (set coll) | |
(map (fn [[k c]] (MapEntry. k (set c))) (partition 2 key-colls))))) | |
(defn multi-map [& keyvals] | |
(into mm-empty (partition 2 keyvals))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment