").append(n.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,e||[a.responseText,b,a])}),this},n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};var dd=a.document.documentElement;function ed(a){return n.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,"position"),l=n(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=n.css(a,"top"),i=n.css(a,"left"),j=("absolute"===k||"fixed"===k)&&n.inArray("auto",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,n.contains(b,e)?(typeof e.getBoundingClientRect!==L&&(d=e.getBoundingClientRect()),c=ed(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===n.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(c=a.offset()),c.top+=n.css(a[0],"borderTopWidth",!0),c.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-n.css(d,"marginTop",!0),left:b.left-c.left-n.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||dd;while(a&&!n.nodeName(a,"html")&&"static"===n.css(a,"position"))a=a.offsetParent;return a||dd})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);n.fn[a]=function(d){return W(this,function(a,d,e){var f=ed(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?n(f).scrollLeft():e,c?e:n(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=Mb(l.pixelPosition,function(a,c){return c?(c=Kb(a,b),Ib.test(c)?n(a).position()[b]+"px":c):void 0})}),n.each({Height:"height",Width:"width"},function(a,b){n.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return W(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var fd=a.jQuery,gd=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=gd),b&&a.jQuery===n&&(a.jQuery=fd),n},typeof b===L&&(a.jQuery=a.$=n),n});
diff --git a/doc/js/page_effects.js b/doc/js/page_effects.js
deleted file mode 100644
index ef8120d..0000000
--- a/doc/js/page_effects.js
+++ /dev/null
@@ -1,99 +0,0 @@
-function visibleInParent(element) {
- var position = $(element).position().top
- return position > -50 && position < ($(element).offsetParent().height() - 50)
-}
-
-function hasFragment(link, fragment) {
- return $(link).attr("href").indexOf("#" + fragment) != -1
-}
-
-function findLinkByFragment(elements, fragment) {
- return $(elements).filter(function(i, e) { return hasFragment(e, fragment)}).first()
-}
-
-function scrollToCurrentVarLink(elements) {
- var elements = $(elements);
- var parent = elements.offsetParent();
-
- if (elements.length == 0) return;
-
- var top = elements.first().position().top;
- var bottom = elements.last().position().top + elements.last().height();
-
- if (top >= 0 && bottom <= parent.height()) return;
-
- if (top < 0) {
- parent.scrollTop(parent.scrollTop() + top);
- }
- else if (bottom > parent.height()) {
- parent.scrollTop(parent.scrollTop() + bottom - parent.height());
- }
-}
-
-function setCurrentVarLink() {
- $('#vars a').parent().removeClass('current')
- $('.anchor').
- filter(function(index) { return visibleInParent(this) }).
- each(function(index, element) {
- findLinkByFragment("#vars a", element.id).
- parent().
- addClass('current')
- });
- scrollToCurrentVarLink('#vars .current');
-}
-
-var hasStorage = (function() { try { return localStorage.getItem } catch(e) {} }())
-
-function scrollPositionId(element) {
- var directory = window.location.href.replace(/[^\/]+\.html$/, '')
- return 'scroll::' + $(element).attr('id') + '::' + directory
-}
-
-function storeScrollPosition(element) {
- if (!hasStorage) return;
- localStorage.setItem(scrollPositionId(element) + "::x", $(element).scrollLeft())
- localStorage.setItem(scrollPositionId(element) + "::y", $(element).scrollTop())
-}
-
-function recallScrollPosition(element) {
- if (!hasStorage) return;
- $(element).scrollLeft(localStorage.getItem(scrollPositionId(element) + "::x"))
- $(element).scrollTop(localStorage.getItem(scrollPositionId(element) + "::y"))
-}
-
-function persistScrollPosition(element) {
- recallScrollPosition(element)
- $(element).scroll(function() { storeScrollPosition(element) })
-}
-
-function sidebarContentWidth(element) {
- var widths = $(element).find('.inner').map(function() { return $(this).innerWidth() })
- return Math.max.apply(Math, widths)
-}
-
-function resizeSidebars() {
- var nsWidth = sidebarContentWidth('#namespaces') + 30
- var varWidth = 0
-
- if ($('#vars').length != 0) {
- varWidth = sidebarContentWidth('#vars') + 30
- }
-
- // snap to grid
- var snap = 30;
- nsWidth = Math.ceil(nsWidth / snap) * snap;
- varWidth = Math.ceil(varWidth / snap) * snap;
-
- $('#namespaces').css('width', nsWidth)
- $('#vars').css('width', varWidth)
- $('#vars, .namespace-index').css('left', nsWidth + 1)
- $('.namespace-docs').css('left', nsWidth + varWidth + 2)
-}
-
-$(window).ready(resizeSidebars)
-$(window).ready(setCurrentVarLink)
-$(window).ready(function() { persistScrollPosition('#namespaces')})
-$(window).ready(function() {
- $('#content').scroll(setCurrentVarLink)
- $(window).resize(setCurrentVarLink)
-})
diff --git a/doc/linked.map.html b/doc/linked.map.html
deleted file mode 100644
index 4fbbaa5..0000000
--- a/doc/linked.map.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
linked.map documentationlinked.map
->LinkedMap
(->LinkedMap head delegate-map)
Positional factory function for class linked.map.LinkedMap.
-
->Node
(->Node value left right)
Positional factory function for class linked.map.Node.
-
map->Node
(map->Node m__6289__auto__)
Factory function for class linked.map.Node, taking a map of keywords to field values.
-
\ No newline at end of file
diff --git a/doc/linked.set.html b/doc/linked.set.html
deleted file mode 100644
index e521191..0000000
--- a/doc/linked.set.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
linked.set documentationlinked.set
->LinkedSet
(->LinkedSet linked-map)
Positional factory function for class linked.set.LinkedSet.
-
\ No newline at end of file
diff --git a/project.clj b/project.clj
deleted file mode 100644
index 3dee8d1..0000000
--- a/project.clj
+++ /dev/null
@@ -1,53 +0,0 @@
-(defproject frankiesardo/linked "1.2.4-SNAPSHOT"
- :description "Efficient ordered map and set"
- :url "http://github.com/frankiesardo/linked"
- :license {:name "Eclipse Public License"
- :url "http://www.eclipse.org/legal/epl-v10.html"}
- :profiles {:dev {:dependencies [[org.clojure/clojure "1.7.0"
- :scope "provided"]
- [org.clojure/clojurescript "1.7.58"
- :scope "provided"]]
- :plugins [[com.keminglabs/cljx "0.6.0"
- :exclusions [org.clojure/clojure]]
- [lein-cljsbuild "1.0.5"]
- [com.cemerick/clojurescript.test "0.3.3"]
- [codox "0.8.10"]]
- :cljx {:builds [{:source-paths ["src"]
- :output-path "target/classes"
- :rules :clj}
- {:source-paths ["src"]
- :output-path "target/classes"
- :rules :cljs}
- {:source-paths ["test"]
- :output-path "target/test-classes"
- :rules :clj}
- {:source-paths ["test"]
- :output-path "target/test-classes"
- :rules :cljs}]}}}
- :codox {:src-dir-uri "http://github.com/frankiesardo/linked/blob/master/"
- :src-uri-mapping {#"target/classes" #(str "src/" % "x")}
- :src-linenum-anchor-prefix "L"}
- :aliases {"test" ["do" "clean," "cljx" "once," "test," "cljsbuild" "test"]
- "check" ["do" "clean," "cljx" "once," "check"]}
- :release-tasks [["vcs" "assert-committed"]
- ["change" "version" "leiningen.release/bump-version" "release"]
- ["cljx" "once"]
- ["doc"]
- ["vcs" "commit"]
- ["vcs" "tag" "v"]
- ["deploy" "clojars"]
- ["rsync" "doc/" "gh-pages"]
- ["change" "version" "leiningen.release/bump-version"]
- ["vcs" "commit"]
- ["vcs" "push"]]
- :auto-clean false
- :jar-exclusions [#"\.cljx"]
- :cljsbuild {:test-commands
- {"phantom" ["phantomjs" :runner "target/testable.js"]}
- :builds
- [{:source-paths ["target/classes" "target/test-classes"]
- :compiler {:output-to "target/testable.js"
- :optimizations :whitespace
- :pretty-print true}}]}
- :source-paths ["src" "target/classes"]
- :test-paths ["test" "target/test-classes"])
diff --git a/src/linked/core.cljc b/src/linked/core.cljc
new file mode 100644
index 0000000..8c1c4c7
--- /dev/null
+++ b/src/linked/core.cljc
@@ -0,0 +1,12 @@
+(ns linked.core
+ (:refer-clojure :exclude [map set])
+ (:require [linked.map :as m]
+ [linked.set :as s]))
+
+(defn map
+ ([] m/empty-linked-map)
+ ([& keyvals] (apply assoc m/empty-linked-map keyvals)))
+
+(defn set
+ ([] s/empty-linked-set)
+ ([& keys] (apply conj s/empty-linked-set keys)))
diff --git a/src/linked/map.cljc b/src/linked/map.cljc
new file mode 100644
index 0000000..f39a9ef
--- /dev/null
+++ b/src/linked/map.cljc
@@ -0,0 +1,283 @@
+(ns linked.map
+ (:require [clojure.string :as string]
+ #?(:cljs [cljs.reader :as reader]))
+ #?(:clj (:import (clojure.lang Associative
+ Counted
+ IObj
+ IFn
+ ILookup
+ IPersistentCollection
+ IPersistentVector
+ IPersistentMap
+ MapEntry
+ MapEquivalence
+ Reversible
+ Seqable
+ SeqIterator)
+ (java.util Map
+ Map$Entry)
+ (java.lang Iterable))))
+
+(declare empty-linked-map)
+
+(defrecord Node [value left right])
+
+(declare assoc*)
+(declare dissoc*)
+(declare seq*)
+(declare rseq*)
+
+(deftype LinkedMap [head delegate-map]
+ #?@(:clj
+ [IPersistentMap
+ (assoc [this k v]
+ (assoc* this k v))
+ (assocEx [this k v]
+ (if (.containsKey this k)
+ (throw (RuntimeException. "Key already present"))
+ (assoc this k v)))
+ (without [this k]
+ (dissoc* this k))
+
+ MapEquivalence
+
+ Map
+ (get [this k]
+ (.valAt this k))
+ (containsValue [this v]
+ (boolean (seq (filter #(= % v) (.values this)))))
+ (values [this]
+ (map val (.seq this)))
+ (size [_]
+ (count delegate-map))
+
+ Counted
+
+ IPersistentCollection
+ (count [this]
+ (.size this))
+ (cons [this o]
+ (condp instance? o
+ Map$Entry (let [^Map$Entry e o]
+ (.assoc this (.getKey e) (.getValue e)))
+ IPersistentVector (if (= 2 (count o))
+ (.assoc this (nth o 0) (nth o 1))
+ (throw (IllegalArgumentException. "Vector arg to map conj must be a pair")))
+ ;; TODO support for transient to speed up multiple assoc?
+ (reduce (fn [^IPersistentMap m ^Map$Entry e]
+ (.assoc m (.getKey e) (.getValue e)))
+ this
+ o)))
+ (empty [_]
+ (with-meta empty-linked-map (meta delegate-map)))
+ (equiv [this o]
+ (and (instance? Map o)
+ (= (.count this) (count o))
+ (every? (fn [[k v]]
+ (= v (get o k)))
+ (.seq this))))
+
+ Seqable
+ (seq [this]
+ (seq* this))
+
+ Reversible
+ (rseq [this]
+ (rseq* this))
+
+ Iterable
+ (iterator [this]
+ (SeqIterator. (.seq this)))
+
+ Associative
+ (containsKey [_ k]
+ (contains? delegate-map k))
+ (entryAt [this k]
+ (when (.containsKey this k)
+ (MapEntry. k (.valAt this k))))
+
+ ILookup
+ (valAt [this k]
+ (.valAt this k nil))
+ (valAt [_ k not-found]
+ (if-let [entry (find delegate-map k)]
+ (-> entry val :value)
+ not-found))
+
+ IFn
+ (invoke [this k]
+ (.valAt this k))
+ (invoke [this k not-found]
+ (.valAt this k not-found))
+
+ IObj
+ (meta [this]
+ (.meta ^IObj delegate-map))
+ (withMeta [this m]
+ (LinkedMap. head (.withMeta ^IObj delegate-map m)))
+
+ ;; IEditableCollection
+
+ Object
+ (toString [this]
+ (str "{" (string/join ", " (for [[k v] this] (str k " " v))) "}"))
+ (equals [this other]
+ (.equiv this other))
+ (hashCode [this]
+ (hash (into {} this)))]
+ :cljs
+ [Object
+ (toString [coll]
+ (str "{" (string/join ", " (for [[k v] coll] (str k " " v))) "}"))
+ (equiv [this other]
+ (-equiv this other))
+
+ ICloneable
+ (-clone [_]
+ (LinkedMap. head delegate-map))
+
+ IWithMeta
+ (-with-meta [coll meta]
+ (LinkedMap. head (with-meta delegate-map meta)))
+
+ IMeta
+ (-meta [coll] (meta delegate-map))
+
+ ICollection
+ (-conj [coll entry]
+ (if (vector? entry)
+ (-assoc coll (-nth entry 0) (-nth entry 1))
+ (loop [ret coll es (seq entry)]
+ (if (nil? es)
+ ret
+ (let [e (first es)]
+ (if (vector? e)
+ (recur (-assoc ret (-nth e 0) (-nth e 1))
+ (next es))
+ (throw (js/Error. "conj on a map takes map entries or seqables of map entries"))))))))
+
+ IEmptyableCollection
+ (-empty [coll] (-with-meta empty-linked-map (meta delegate-map)))
+
+ IEquiv
+ (-equiv [coll other] (equiv-map coll other))
+
+ IHash
+ (-hash [coll] (hash-unordered-coll coll))
+
+ ISequential
+
+ ISeqable
+ (-seq [coll] (seq* coll))
+
+ IReversible
+ (-rseq [coll] (rseq* coll))
+
+ ICounted
+ (-count [coll]
+ (count delegate-map))
+
+ ILookup
+ (-lookup [coll k]
+ (-lookup coll k nil))
+
+ (-lookup [coll k not-found]
+ (if-let [entry (find delegate-map k)]
+ (-> entry val :value)
+ not-found))
+
+ IAssociative
+ (-assoc [coll k v]
+ (assoc* coll k v))
+
+ (-contains-key? [coll k]
+ (contains? delegate-map k))
+
+ IMap
+ (-dissoc [coll k]
+ (dissoc* coll k))
+
+ IKVReduce
+ (-kv-reduce [coll f init]
+ (reduce (seq coll) f init))
+
+ IFn
+ (-invoke [coll k]
+ (-lookup coll k))
+
+ (-invoke [coll k not-found]
+ (-lookup coll k not-found))
+
+ ;; IEditableCollection
+
+ IPrintWithWriter
+ (-pr-writer [coll writer opts] (-write writer (str "#linked/map " (into [] coll))))]))
+
+#?(:clj
+ (defmethod print-method LinkedMap [o ^java.io.Writer w]
+ (.write w "#linked/map ")
+ (.write w (pr-str (into [] o)))))
+
+(defn- assoc* [^LinkedMap this k v]
+ (let [head (.-head this)
+ delegate-map (.-delegate-map this)]
+ (if-let [entry (find delegate-map k)]
+ (LinkedMap. head (assoc-in delegate-map [k :value] v))
+ (if (empty? delegate-map)
+ (LinkedMap. k (assoc delegate-map k (Node. v k k)))
+ (let [tail (get-in delegate-map [head :left])]
+ (LinkedMap. head (-> delegate-map
+ (assoc k (Node. v tail head))
+ (assoc-in [head :left] k)
+ (assoc-in [tail :right] k))))))))
+
+(defn- dissoc* [^LinkedMap this k]
+ (let [head (.-head this)
+ delegate-map (.-delegate-map this)]
+ (if-let [entry (find delegate-map k)]
+ (if (= 1 (count delegate-map))
+ (empty this)
+ (let [rk (-> entry val :right)
+ lk (-> entry val :left)
+ head (if (= k head) rk head)]
+ (LinkedMap. head (-> delegate-map
+ (dissoc k)
+ (assoc-in [rk :left] lk)
+ (assoc-in [lk :right] rk)))))
+ this)))
+
+
+;;;; seq and rseq impl
+
+(defn- map-entry [k v]
+ #?(:clj (MapEntry. k v)
+ :cljs (vector k v)))
+
+(defn- visit-node [delegate-map current last direction]
+ (let [[k node] (find delegate-map current)
+ entry (map-entry k (:value node))
+ next (direction node)]
+ (if (= current last)
+ (list entry)
+ (cons entry (lazy-seq (visit-node delegate-map next last direction))))))
+
+(defn- seq* [^LinkedMap this]
+ (let [delegate-map (.-delegate-map this)
+ head (.-head this)
+ tail (get-in delegate-map [head :left])]
+ (when (seq delegate-map)
+ (visit-node delegate-map head tail :right))))
+
+(defn- rseq* [^LinkedMap this]
+ (let [delegate-map (.-delegate-map this)
+ head (.-head this)
+ tail (get-in delegate-map [head :left])]
+ (when (seq delegate-map)
+ (visit-node delegate-map tail head :left))))
+
+(def ^{:tag LinkedMap} empty-linked-map
+ (LinkedMap. nil (hash-map)))
+
+(def ->linked-map (partial into empty-linked-map))
+
+#?(:cljs (reader/register-tag-parser! "linked/map" ->linked-map))
diff --git a/src/linked/set.cljc b/src/linked/set.cljc
new file mode 100644
index 0000000..b73bc0d
--- /dev/null
+++ b/src/linked/set.cljc
@@ -0,0 +1,159 @@
+(ns linked.set
+ (:require [linked.map :refer [empty-linked-map]]
+ [clojure.string :as string]
+ #?(:cljs [cljs.reader :as reader]))
+ #?(:clj (:import (clojure.lang Counted
+ IObj
+ IFn
+ ILookup
+ IPersistentCollection
+ IPersistentSet
+ IPersistentVector
+ Reversible
+ Seqable
+ SeqIterator)
+ (java.util Set)
+ (java.lang Iterable))))
+
+(declare empty-linked-set)
+
+(deftype LinkedSet [linked-map]
+ #?@(:clj
+ [IPersistentSet
+ (disjoin [_ k]
+ (LinkedSet. (dissoc linked-map k)))
+ (contains [_ k]
+ (contains? linked-map k))
+ (get [this k]
+ (when (.contains this k) k))
+
+ Set
+ (size [this]
+ (.count this))
+
+ Iterable
+ (iterator [this]
+ (SeqIterator. (.seq this)))
+
+ Counted
+
+ IPersistentCollection
+ (count [_]
+ (count linked-map))
+ (cons [this o]
+ (if (contains? linked-map o)
+ this
+ (LinkedSet. (assoc linked-map o nil))))
+ (empty [_]
+ empty-linked-set)
+ (equiv [this other]
+ (or (identical? this other)
+ (and (instance? Set other)
+ (let [^Set s other]
+ (and (= (.size this) (.size s))
+ (every? #(.contains s %) (.seq this)))))))
+ Seqable
+ (seq [_]
+ (when-let [s (seq linked-map)] (map key s)))
+
+ Reversible
+ (rseq [_]
+ (when-let [s (rseq linked-map)] (map key s)))
+
+ IFn
+ (invoke [this k]
+ (get this k))
+
+ IObj
+ (meta [this]
+ (.meta ^IObj linked-map))
+ (withMeta [this m]
+ (LinkedSet. (.withMeta ^IObj linked-map m)))
+
+ Object
+ (toString [this]
+ (str "[" (string/join " " (map str this)) "]"))
+ (hashCode [this]
+ (reduce + (map hash (.seq this))))
+ (equals [this other]
+ (.equiv this other))]
+ :cljs
+ [Object
+ (toString [this]
+ (str "[" (string/join " " (map str this)) "]"))
+ (equiv [this other]
+ (-equiv this other))
+
+ ICloneable
+ (-clone [_] (LinkedSet. linked-map))
+
+ IWithMeta
+ (-with-meta [coll meta] (LinkedSet. (with-meta linked-map meta)))
+
+ IMeta
+ (-meta [coll] (meta linked-map))
+
+ ICollection
+ (-conj [coll o]
+ (LinkedSet. (assoc linked-map o nil)))
+
+ IEmptyableCollection
+ (-empty [coll] (with-meta empty-linked-set meta))
+
+ IEquiv
+ (-equiv [coll other]
+ (and
+ (set? other)
+ (== (count coll) (count other))
+ (every? #(contains? coll %)
+ other)))
+
+ IHash
+ (-hash [coll] (hash-unordered-coll coll))
+
+ ISeqable
+ (-seq [coll] (when-let [s (seq linked-map)] (map key s)))
+
+ IReversible
+ (-rseq [coll] (when-let [s (rseq linked-map)] (map key s)))
+
+ ISequential
+
+ ICounted
+ (-count [coll] (-count linked-map))
+
+ ILookup
+ (-lookup [coll v]
+ (-lookup coll v nil))
+ (-lookup [coll v not-found]
+ (if (-contains-key? linked-map v)
+ v
+ not-found))
+
+ ISet
+ (-disjoin [coll v]
+ (LinkedSet. (-dissoc linked-map v)))
+
+ IFn
+ (-invoke [coll k]
+ (-lookup coll k))
+ (-invoke [coll k not-found]
+ (-lookup coll k not-found))
+
+ ;; IEditableCollection
+
+ IPrintWithWriter
+ (-pr-writer [coll writer opts]
+ (-write writer (str "#linked/set " (into [] coll))))]))
+
+#?(:clj
+ (defmethod print-method LinkedSet [o ^java.io.Writer w]
+ (.write w "#linked/set ")
+ (print-method (into [] o) w)))
+
+(def ^{:tag LinkedSet} empty-linked-set
+ (LinkedSet. empty-linked-map))
+
+(def ->linked-set (partial into empty-linked-set))
+
+#?(:cljs (reader/register-tag-parser! "linked/set" ->linked-set))
diff --git a/src/linked/set.cljx b/src/linked/set.cljx
deleted file mode 100644
index 041414b..0000000
--- a/src/linked/set.cljx
+++ /dev/null
@@ -1,162 +0,0 @@
-(ns linked.set
- (:require [linked.map :refer [empty-linked-map]]
- [clojure.string :as string]
- #+cljs [cljs.reader :as reader])
- #+clj (:import (clojure.lang Counted
- IObj
- IFn
- ILookup
- IPersistentCollection
- IPersistentSet
- IPersistentVector
- Reversible
- Seqable
- SeqIterator)
- (java.util Set)
- (java.lang Iterable)))
-
-(declare empty-linked-set)
-
-#+clj
-(deftype LinkedSet [linked-map]
- IPersistentSet
- (disjoin [_ k]
- (LinkedSet. (dissoc linked-map k)))
- (contains [_ k]
- (contains? linked-map k))
- (get [this k]
- (when (.contains this k) k))
-
- Set
- (size [this]
- (.count this))
-
- Iterable
- (iterator [this]
- (SeqIterator. (.seq this)))
-
- Counted
-
- IPersistentCollection
- (count [_]
- (count linked-map))
- (cons [this o]
- (if (contains? linked-map o)
- this
- (LinkedSet. (assoc linked-map o nil))))
- (empty [_]
- empty-linked-set)
- (equiv [this other]
- (or (identical? this other)
- (and (instance? Set other)
- (let [^Set s other]
- (and (= (.size this) (.size s))
- (every? #(.contains s %) (.seq this)))))))
- Seqable
- (seq [_]
- (when-let [s (seq linked-map)] (map key s)))
-
- Reversible
- (rseq [_]
- (when-let [s (rseq linked-map)] (map key s)))
-
- IFn
- (invoke [this k]
- (get this k))
-
- IObj
- (meta [this]
- (.meta ^IObj linked-map))
- (withMeta [this m]
- (LinkedSet. (.withMeta ^IObj linked-map m)))
-
- Object
- (toString [this]
- (str "[" (string/join " " (map str this)) "]"))
- (hashCode [this]
- (reduce + (map hash (.seq this))))
- (equals [this other]
- (.equiv this other)))
-
-#+clj
-(defmethod print-method LinkedSet [o ^java.io.Writer w]
- (.write w "#linked/set ")
- (print-method (into [] o) w))
-
-
-#+cljs
-(deftype LinkedSet [linked-map]
- Object
- (toString [this]
- (str "[" (string/join " " (map str this)) "]"))
- (equiv [this other]
- (-equiv this other))
-
- ICloneable
- (-clone [_] (LinkedSet. linked-map))
-
- IWithMeta
- (-with-meta [coll meta] (LinkedSet. (with-meta linked-map meta)))
-
- IMeta
- (-meta [coll] (meta linked-map))
-
- ICollection
- (-conj [coll o]
- (LinkedSet. (assoc linked-map o nil)))
-
- IEmptyableCollection
- (-empty [coll] (with-meta empty-linked-set meta))
-
- IEquiv
- (-equiv [coll other]
- (and
- (set? other)
- (== (count coll) (count other))
- (every? #(contains? coll %)
- other)))
-
- IHash
- (-hash [coll] (hash-unordered-coll coll))
-
- ISeqable
- (-seq [coll] (when-let [s (seq linked-map)] (map key s)))
-
- IReversible
- (-rseq [coll] (when-let [s (rseq linked-map)] (map key s)))
-
- ISequential
-
- ICounted
- (-count [coll] (-count linked-map))
-
- ILookup
- (-lookup [coll v]
- (-lookup coll v nil))
- (-lookup [coll v not-found]
- (if (-contains-key? linked-map v)
- v
- not-found))
-
- ISet
- (-disjoin [coll v]
- (LinkedSet. (-dissoc linked-map v)))
-
- IFn
- (-invoke [coll k]
- (-lookup coll k))
- (-invoke [coll k not-found]
- (-lookup coll k not-found))
-
- ;; IEditableCollection
-
- IPrintWithWriter
- (-pr-writer [coll writer opts]
- (-write writer (str "#linked/set " (into [] coll)))))
-
-(def ^{:tag LinkedSet} empty-linked-set
- (LinkedSet. empty-linked-map))
-
-(def ->linked-set (partial into empty-linked-set))
-
-#+cljs (reader/register-tag-parser! "linked/set" ->linked-set)
diff --git a/test/linked/map_test.cljx b/test/linked/map_test.cljc
similarity index 83%
rename from test/linked/map_test.cljx
rename to test/linked/map_test.cljc
index 074e50a..8beedc6 100644
--- a/test/linked/map_test.cljx
+++ b/test/linked/map_test.cljc
@@ -1,32 +1,29 @@
(ns linked.map-test
(:require [linked.core :as linked]
- #+clj [clojure.test :refer :all]
- #+cljs [cemerick.cljs.test]
- #+cljs [cljs.reader :refer [read-string]])
- #+cljs (:require-macros
- [cemerick.cljs.test :refer
- [deftest is are testing run-tests]]))
+ #?(:clj [clojure.test :refer :all]
+ :cljs [cljs.test :refer-macros [is are testing deftest run-tests]])
+ #?(:cljs [cljs.reader :refer [read-string]])))
-#+clj
-(deftest implementations
- (let [basic (linked/map)]
- (testing "Interfaces marked as implemented"
- (are [class] (instance? class basic)
+#?(:clj
+ (deftest implementations
+ (let [basic (linked/map)]
+ (testing "Interfaces marked as implemented"
+ (are [class] (instance? class basic)
clojure.lang.IPersistentMap
clojure.lang.IPersistentCollection
clojure.lang.Counted
clojure.lang.Associative
java.util.Map))
- (testing "Behavior smoke testing"
- (testing "Most operations don't change type"
- (are [object] (= (class object) (class basic))
+ (testing "Behavior smoke testing"
+ (testing "Most operations don't change type"
+ (are [object] (= (class object) (class basic))
(conj basic [1 2])
(assoc basic 1 2)
(into basic {1 2})))
- (testing "Seq-oriented operations return nil when empty"
- (are [object] (nil? object)
+ (testing "Seq-oriented operations return nil when empty"
+ (are [object] (nil? object)
(seq basic)
- (rseq basic))))))
+ (rseq basic)))))))
(deftest equality
(let [empty-map (linked/map)
@@ -121,6 +118,6 @@
(is (= "#linked/map [[1 9] [3 4] [5 6] [7 8]]"
(pr-str s)))
(let [o (read-string (pr-str s))]
- #+clj (is (= linked.map.LinkedMap (type o)))
+ #?(:clj (is (= linked.map.LinkedMap (type o))))
(is (= '([1 9] [3 4] [5 6] [7 8])
(seq o))))))
diff --git a/test/linked/set_test.cljx b/test/linked/set_test.cljc
similarity index 78%
rename from test/linked/set_test.cljx
rename to test/linked/set_test.cljc
index 647d9ce..618d482 100644
--- a/test/linked/set_test.cljx
+++ b/test/linked/set_test.cljc
@@ -1,31 +1,28 @@
(ns linked.set-test
(:require [linked.core :as linked]
- #+clj [clojure.test :refer :all]
- #+cljs [cemerick.cljs.test]
- #+cljs [cljs.reader :refer [read-string]])
- #+cljs (:require-macros
- [cemerick.cljs.test :refer
- [deftest is are testing run-tests]]))
+ #?(:clj [clojure.test :refer :all]
+ :cljs [cljs.test :refer-macros [is are testing deftest run-tests]])
+ #?(:cljs [cljs.reader :refer [read-string]])))
-#+clj
-(deftest implementations
- (let [s (linked/set)]
- (testing "Interfaces marked as implemented"
- (are [class] (instance? class s)
+#?(:clj
+ (deftest implementations
+ (let [s (linked/set)]
+ (testing "Interfaces marked as implemented"
+ (are [class] (instance? class s)
clojure.lang.IPersistentSet
clojure.lang.IPersistentCollection
clojure.lang.Counted
java.util.Set))
- (testing "Behavior smoke testing"
- (testing "Most operations don't change type"
- (are [object] (= (class object) (class s))
+ (testing "Behavior smoke testing"
+ (testing "Most operations don't change type"
+ (are [object] (= (class object) (class s))
(conj s 1 2)
(disj s 1)
(into s #{1 2})))
- (testing "Seq-oriented operations return nil when empty"
- (are [object] (nil? object)
+ (testing "Seq-oriented operations return nil when empty"
+ (are [object] (nil? object)
(seq s)
- (rseq s))))))
+ (rseq s)))))))
(deftest equality
(let [empty (linked/set)
@@ -94,6 +91,6 @@
(is (= "#linked/set [1 2 9 8 7 5]"
(pr-str s)))
(let [o (read-string (pr-str s))]
- #+clj (is (= linked.set.LinkedSet (type o)))
+ #?(:clj (is (= linked.set.LinkedSet (type o))))
(is (= '(1 2 9 8 7 5)
(seq o))))))