@@ -12400,3 +12400,372 @@ reduces them without incurring seq initialization"
12400
12400
(identical? " window" *global*) (set! goog/global js/window)
12401
12401
(identical? " self" *global*) (set! goog/global js/self)
12402
12402
(identical? " global" *global*) (set! goog/global js/global)))
12403
+
12404
+ ; ; -----------------------------------------------------------------------------
12405
+ ; ; Original 2011 Copy-on-Write Types
12406
+
12407
+ ; ;; Vector
12408
+
12409
+ (deftype Vector [meta array]
12410
+ IWithMeta
12411
+ (-with-meta [coll meta] (Vector. meta array))
12412
+
12413
+ IMeta
12414
+ (-meta [coll] meta)
12415
+
12416
+ IStack
12417
+ (-peek [coll]
12418
+ (let [count (.-length array)]
12419
+ (when (> count 0 )
12420
+ (aget array (dec count)))))
12421
+ (-pop [coll]
12422
+ (if (> (.-length array) 0 )
12423
+ (let [new-array (aclone array)]
12424
+ (. new-array (pop ))
12425
+ (Vector. meta new-array))
12426
+ (throw (js/Error. " Can't pop empty vector" ))))
12427
+
12428
+ ICollection
12429
+ (-conj [coll o]
12430
+ (let [new-array (aclone array)]
12431
+ (.push new-array o)
12432
+ (Vector. meta new-array)))
12433
+
12434
+ IEmptyableCollection
12435
+ (-empty [coll] (with-meta (. Vector -EMPTY) meta))
12436
+
12437
+ ISequential
12438
+ IEquiv
12439
+ (-equiv [coll other] (equiv-sequential coll other))
12440
+
12441
+ IHash
12442
+ (-hash [coll] (hash-coll coll))
12443
+
12444
+ ISeqable
12445
+ (-seq [coll]
12446
+ (when (> (.-length array) 0 )
12447
+ (let [vector-seq
12448
+ (fn vector-seq [i]
12449
+ (lazy-seq
12450
+ (when (< i (.-length array))
12451
+ (cons (aget array i) (vector-seq (inc i))))))]
12452
+ (vector-seq 0 ))))
12453
+
12454
+ ICounted
12455
+ (-count [coll] (.-length array))
12456
+
12457
+ IIndexed
12458
+ (-nth [coll n]
12459
+ (if (and (<= 0 n) (< n (.-length array)))
12460
+ (aget array n)
12461
+ #_(throw (js/Error. (str " No item " n " in vector of length " (.-length array))))))
12462
+ (-nth [coll n not-found]
12463
+ (if (and (<= 0 n) (< n (.-length array)))
12464
+ (aget array n)
12465
+ not-found))
12466
+
12467
+ ILookup
12468
+ (-lookup [coll k] (-nth coll k nil ))
12469
+ (-lookup [coll k not-found] (-nth coll k not-found))
12470
+
12471
+ IAssociative
12472
+ (-assoc [coll k v]
12473
+ (let [new-array (aclone array)]
12474
+ (aset new-array k v)
12475
+ (Vector. meta new-array)))
12476
+
12477
+ IVector
12478
+ (-assoc-n [coll n val] (-assoc coll n val))
12479
+
12480
+ IReduce
12481
+ (-reduce [v f]
12482
+ (ci-reduce array f))
12483
+ (-reduce [v f start]
12484
+ (ci-reduce array f start))
12485
+
12486
+ IFn
12487
+ (-invoke [coll k]
12488
+ (-lookup coll k))
12489
+ (-invoke [coll k not-found]
12490
+ (-lookup coll k not-found))
12491
+
12492
+ IPrintWithWriter
12493
+ (-pr-writer [coll writer opts] (pr-sequential-writer writer pr-writer " [" " " " ]" opts coll)))
12494
+
12495
+ (set! (. Vector -EMPTY) (Vector. nil (array )))
12496
+
12497
+ (set! (. Vector -fromArray) (fn [xs] (Vector. nil xs)))
12498
+
12499
+ ; The keys field is an array of all keys of this map, in no particular
12500
+ ; order. Any string, keyword, or symbol key is used as a property name
12501
+ ; to store the value in strobj. If a key is assoc'ed when that same
12502
+ ; key already exists in strobj, the old value is overwritten. If a
12503
+ ; non-string key is assoc'ed, return a HashMap object instead.
12504
+
12505
+ (defn- obj-map-contains-key?
12506
+ ([k strobj]
12507
+ (obj-map-contains-key? k strobj true false ))
12508
+ ([k strobj true -val false -val]
12509
+ (if (and (goog/isString k) (.hasOwnProperty strobj k))
12510
+ true -val
12511
+ false -val)))
12512
+
12513
+ (defn- obj-map-compare-keys [a b]
12514
+ (let [a (hash a)
12515
+ b (hash b)]
12516
+ (cond
12517
+ (< a b) -1
12518
+ (> a b) 1
12519
+ :else 0 )))
12520
+
12521
+ (deftype ObjMap [meta keys strobj]
12522
+ IWithMeta
12523
+ (-with-meta [coll meta] (ObjMap. meta keys strobj))
12524
+
12525
+ IMeta
12526
+ (-meta [coll] meta)
12527
+
12528
+ ICollection
12529
+ (-conj [coll entry]
12530
+ (if (vector? entry)
12531
+ (-assoc coll (-nth entry 0 ) (-nth entry 1 ))
12532
+ (reduce -conj
12533
+ coll
12534
+ entry)))
12535
+
12536
+ IEmptyableCollection
12537
+ (-empty [coll] (with-meta (. ObjMap -EMPTY) meta))
12538
+
12539
+ IEquiv
12540
+ (-equiv [coll other] (equiv-map coll other))
12541
+
12542
+ IHash
12543
+ (-hash [coll] (hash-coll coll))
12544
+
12545
+ ISeqable
12546
+ (-seq [coll]
12547
+ (when (pos? (.-length keys))
12548
+ (map #(vector % (aget strobj %))
12549
+ (.sort keys obj-map-compare-keys))))
12550
+
12551
+ ICounted
12552
+ (-count [coll] (.-length keys))
12553
+
12554
+ ILookup
12555
+ (-lookup [coll k] (-lookup coll k nil ))
12556
+ (-lookup [coll k not-found]
12557
+ (obj-map-contains-key? k strobj (aget strobj k) not-found))
12558
+
12559
+ IAssociative
12560
+ (-assoc [coll k v]
12561
+ (if (goog/isString k)
12562
+ (let [new-strobj (goog.object/clone strobj)
12563
+ overwrite? (.hasOwnProperty new-strobj k)]
12564
+ (aset new-strobj k v)
12565
+ (if overwrite?
12566
+ (ObjMap. meta keys new-strobj) ; overwrite
12567
+ (let [new-keys (aclone keys)] ; append
12568
+ (.push new-keys k)
12569
+ (ObjMap. meta new-keys new-strobj))))
12570
+ ; non-string key. game over.
12571
+ (with-meta (into (hash-map k v) (seq coll)) meta)))
12572
+ (-contains-key? [coll k]
12573
+ (obj-map-contains-key? k strobj))
12574
+
12575
+ IMap
12576
+ (-dissoc [coll k]
12577
+ (if (and (goog/isString k) (.hasOwnProperty strobj k))
12578
+ (let [new-keys (aclone keys)
12579
+ new-strobj (goog.object/clone strobj)]
12580
+ (.splice new-keys (scan-array 1 k new-keys) 1 )
12581
+ (js-delete new-strobj k)
12582
+ (ObjMap. meta new-keys new-strobj))
12583
+ coll)) ; key not found, return coll unchanged
12584
+
12585
+ IFn
12586
+ (-invoke [coll k]
12587
+ (-lookup coll k))
12588
+ (-invoke [coll k not-found]
12589
+ (-lookup coll k not-found))
12590
+
12591
+ IPrintWithWriter
12592
+ (-pr-writer [coll writer opts]
12593
+ (print-map coll pr-writer writer opts)))
12594
+
12595
+ (set! (. ObjMap -EMPTY) (ObjMap. nil (array ) (js-obj )))
12596
+
12597
+ (set! (. ObjMap -fromObject) (fn [ks obj] (ObjMap. nil ks obj)))
12598
+
12599
+ (defn obj-map
12600
+ " keyval => key val
12601
+ Returns a new object map with supplied mappings."
12602
+ [& keyvals]
12603
+ (let [ks (array )
12604
+ obj (js-obj )]
12605
+ (loop [kvs (seq keyvals)]
12606
+ (if kvs
12607
+ (do (.push ks (first kvs))
12608
+ (gobject/set obj (first kvs) (second kvs))
12609
+ (recur (nnext kvs)))
12610
+ (.fromObject ObjMap ks obj)))))
12611
+
12612
+ ; The keys field is an array of all keys of this map, in no particular
12613
+ ; order. Each key is hashed and the result used as a property name of
12614
+ ; hashobj. Each values in hashobj is actually a bucket in order to handle hash
12615
+ ; collisions. A bucket is an array of alternating keys (not their hashes) and
12616
+ ; vals.
12617
+ (deftype HashMap [meta count hashobj]
12618
+ IWithMeta
12619
+ (-with-meta [coll meta] (HashMap. meta count hashobj))
12620
+
12621
+ IMeta
12622
+ (-meta [coll] meta)
12623
+
12624
+ ICollection
12625
+ (-conj [coll entry]
12626
+ (if (vector? entry)
12627
+ (-assoc coll (-nth entry 0 ) (-nth entry 1 ))
12628
+ (reduce -conj
12629
+ coll
12630
+ entry)))
12631
+
12632
+ IEmptyableCollection
12633
+ (-empty [coll] (with-meta (. HashMap -EMPTY) meta))
12634
+
12635
+ IEquiv
12636
+ (-equiv [coll other] (equiv-map coll other))
12637
+
12638
+ IHash
12639
+ (-hash [coll] (hash-coll coll))
12640
+
12641
+ ISeqable
12642
+ (-seq [coll]
12643
+ (when (pos? count)
12644
+ (let [hashes (.sort (js-keys hashobj))]
12645
+ (mapcat #(map vec (partition 2 (aget hashobj %)))
12646
+ hashes))))
12647
+
12648
+ ICounted
12649
+ (-count [coll] count)
12650
+
12651
+ ILookup
12652
+ (-lookup [coll k] (-lookup coll k nil ))
12653
+ (-lookup [coll k not-found]
12654
+ (let [bucket (aget hashobj (hash k))
12655
+ i (when bucket (scan-array 2 k bucket))]
12656
+ (if i
12657
+ (aget bucket (inc i))
12658
+ not-found)))
12659
+
12660
+ IAssociative
12661
+ (-assoc [coll k v]
12662
+ (let [h (hash k)
12663
+ bucket (aget hashobj h)]
12664
+ (if bucket
12665
+ (let [new-bucket (aclone bucket)
12666
+ new-hashobj (goog.object/clone hashobj)]
12667
+ (aset new-hashobj h new-bucket)
12668
+ (if-let [i (scan-array 2 k new-bucket)]
12669
+ (do ; found key, replace
12670
+ (aset new-bucket (inc i) v)
12671
+ (HashMap. meta count new-hashobj))
12672
+ (do ; did not find key, append
12673
+ (.push new-bucket k v)
12674
+ (HashMap. meta (inc count) new-hashobj))))
12675
+ (let [new-hashobj (goog.object/clone hashobj)] ; did not find bucket
12676
+ (aset new-hashobj h (array k v))
12677
+ (HashMap. meta (inc count) new-hashobj)))))
12678
+ (-contains-key? [coll k]
12679
+ (let [bucket (aget hashobj (hash k))
12680
+ i (when bucket (scan-array 2 k bucket))]
12681
+ (if i
12682
+ true
12683
+ false )))
12684
+
12685
+ IMap
12686
+ (-dissoc [coll k]
12687
+ (let [h (hash k)
12688
+ bucket (aget hashobj h)
12689
+ i (when bucket (scan-array 2 k bucket))]
12690
+ (if (not i)
12691
+ coll ; key not found, return coll unchanged
12692
+ (let [new-hashobj (goog.object/clone hashobj)]
12693
+ (if (> 3 (.-length bucket))
12694
+ (js-delete new-hashobj h)
12695
+ (let [new-bucket (aclone bucket)]
12696
+ (.splice new-bucket i 2 )
12697
+ (aset new-hashobj h new-bucket)))
12698
+ (HashMap. meta (dec count) new-hashobj)))))
12699
+
12700
+ IFn
12701
+ (-invoke [coll k]
12702
+ (-lookup coll k))
12703
+ (-invoke [coll k not-found]
12704
+ (-lookup coll k not-found))
12705
+
12706
+ IPrintWithWriter
12707
+ (-pr-writer [coll writer opts]
12708
+ (print-map coll pr-writer writer opts)))
12709
+
12710
+ (set! (. HashMap -EMPTY) (HashMap. nil 0 (js-obj )))
12711
+
12712
+ (set! (. HashMap -fromArrays) (fn [ks vs]
12713
+ (let [len (.-length ks)]
12714
+ (loop [i 0 , out (. HashMap -EMPTY)]
12715
+ (if (< i len)
12716
+ (recur (inc i) (assoc out (aget ks i) (aget vs i)))
12717
+ out)))))
12718
+
12719
+ (deftype Set [meta hash-map]
12720
+ IWithMeta
12721
+ (-with-meta [coll meta] (Set. meta hash-map))
12722
+
12723
+ IMeta
12724
+ (-meta [coll] meta)
12725
+
12726
+ ICollection
12727
+ (-conj [coll o]
12728
+ (Set. meta (assoc hash-map o nil )))
12729
+
12730
+ IEmptyableCollection
12731
+ (-empty [coll] (with-meta (. Set -EMPTY) meta))
12732
+
12733
+ IEquiv
12734
+ (-equiv [coll other]
12735
+ (and
12736
+ (set? other)
12737
+ (= (count coll) (count other))
12738
+ (every? #(contains? coll %)
12739
+ other)))
12740
+
12741
+ IHash
12742
+ (-hash [coll] (hash-coll coll))
12743
+
12744
+ ISeqable
12745
+ (-seq [coll] (keys hash-map))
12746
+
12747
+ ICounted
12748
+ (-count [coll] (count (seq coll)))
12749
+
12750
+ ILookup
12751
+ (-lookup [coll v]
12752
+ (-lookup coll v nil ))
12753
+ (-lookup [coll v not-found]
12754
+ (if (-contains-key? hash-map v)
12755
+ v
12756
+ not-found))
12757
+
12758
+ ISet
12759
+ (-disjoin [coll v]
12760
+ (Set. meta (dissoc hash-map v)))
12761
+
12762
+ IFn
12763
+ (-invoke [coll k]
12764
+ (-lookup coll k))
12765
+ (-invoke [coll k not-found]
12766
+ (-lookup coll k not-found))
12767
+
12768
+ IPrintWithWriter
12769
+ (-pr-writer [coll writer opts] (pr-sequential-writer writer pr-writer " #{" " " " }" opts coll)))
12770
+
12771
+ (set! (. Set -EMPTY) (Set. nil (hash-map )))
0 commit comments