@@ -12226,3 +12226,345 @@ reduces them without incurring seq initialization"
12226
12226
(identical? " window" *global*) (set! goog/global js/window)
12227
12227
(identical? " self" *global*) (set! goog/global js/self)
12228
12228
(identical? " global" *global*) (set! goog/global js/global)))
12229
+
12230
+ ; ; -----------------------------------------------------------------------------
12231
+ ; ; Original 2011 Copy-on-Write Types
12232
+
12233
+ ; ;; Vector
12234
+
12235
+ (deftype Vector [meta array]
12236
+ IWithMeta
12237
+ (-with-meta [coll meta] (Vector. meta array))
12238
+
12239
+ IMeta
12240
+ (-meta [coll] meta)
12241
+
12242
+ IStack
12243
+ (-peek [coll]
12244
+ (let [count (.-length array)]
12245
+ (when (> count 0 )
12246
+ (aget array (dec count)))))
12247
+ (-pop [coll]
12248
+ (if (> (.-length array) 0 )
12249
+ (let [new-array (aclone array)]
12250
+ (. new-array (pop ))
12251
+ (Vector. meta new-array))
12252
+ (throw (js/Error. " Can't pop empty vector" ))))
12253
+
12254
+ ICollection
12255
+ (-conj [coll o]
12256
+ (let [new-array (aclone array)]
12257
+ (.push new-array o)
12258
+ (Vector. meta new-array)))
12259
+
12260
+ IEmptyableCollection
12261
+ (-empty [coll] (with-meta cljs.core.Vector/EMPTY meta))
12262
+
12263
+ ISequential
12264
+ IEquiv
12265
+ (-equiv [coll other] (equiv-sequential coll other))
12266
+
12267
+ IHash
12268
+ (-hash [coll] (hash-coll coll))
12269
+
12270
+ ISeqable
12271
+ (-seq [coll]
12272
+ (when (> (.-length array) 0 )
12273
+ (let [vector-seq
12274
+ (fn vector-seq [i]
12275
+ (lazy-seq
12276
+ (when (< i (.-length array))
12277
+ (cons (aget array i) (vector-seq (inc i))))))]
12278
+ (vector-seq 0 ))))
12279
+
12280
+ ICounted
12281
+ (-count [coll] (.-length array))
12282
+
12283
+ IIndexed
12284
+ (-nth [coll n]
12285
+ (if (and (<= 0 n) (< n (.-length array)))
12286
+ (aget array n)
12287
+ #_(throw (js/Error. (str " No item " n " in vector of length " (.-length array))))))
12288
+ (-nth [coll n not-found]
12289
+ (if (and (<= 0 n) (< n (.-length array)))
12290
+ (aget array n)
12291
+ not-found))
12292
+
12293
+ ILookup
12294
+ (-lookup [coll k] (-nth coll k nil ))
12295
+ (-lookup [coll k not-found] (-nth coll k not-found))
12296
+
12297
+ IAssociative
12298
+ (-assoc [coll k v]
12299
+ (let [new-array (aclone array)]
12300
+ (aset new-array k v)
12301
+ (Vector. meta new-array)))
12302
+
12303
+ IVector
12304
+ (-assoc-n [coll n val] (-assoc coll n val))
12305
+
12306
+ IReduce
12307
+ (-reduce [v f]
12308
+ (ci-reduce array f))
12309
+ (-reduce [v f start]
12310
+ (ci-reduce array f start))
12311
+
12312
+ IFn
12313
+ (-invoke [coll k]
12314
+ (-lookup coll k))
12315
+ (-invoke [coll k not-found]
12316
+ (-lookup coll k not-found)))
12317
+
12318
+ (set! (. Vector -EMPTY) (Vector. nil (array )))
12319
+
12320
+ (set! (. Vector -fromArray) (fn [xs] (Vector. nil xs)))
12321
+
12322
+ ; The keys field is an array of all keys of this map, in no particular
12323
+ ; order. Any string, keyword, or symbol key is used as a property name
12324
+ ; to store the value in strobj. If a key is assoc'ed when that same
12325
+ ; key already exists in strobj, the old value is overwritten. If a
12326
+ ; non-string key is assoc'ed, return a HashMap object instead.
12327
+
12328
+ (defn- obj-map-contains-key?
12329
+ ([k strobj]
12330
+ (obj-map-contains-key? k strobj true false ))
12331
+ ([k strobj true -val false -val]
12332
+ (if (and (goog/isString k) (.hasOwnProperty strobj k))
12333
+ true -val
12334
+ false -val)))
12335
+
12336
+ (defn- obj-map-compare-keys [a b]
12337
+ (let [a (hash a)
12338
+ b (hash b)]
12339
+ (cond
12340
+ (< a b) -1
12341
+ (> a b) 1
12342
+ :else 0 )))
12343
+
12344
+ (deftype ObjMap [meta keys strobj]
12345
+ IWithMeta
12346
+ (-with-meta [coll meta] (ObjMap. meta keys strobj))
12347
+
12348
+ IMeta
12349
+ (-meta [coll] meta)
12350
+
12351
+ ICollection
12352
+ (-conj [coll entry]
12353
+ (if (vector? entry)
12354
+ (-assoc coll (-nth entry 0 ) (-nth entry 1 ))
12355
+ (reduce -conj
12356
+ coll
12357
+ entry)))
12358
+
12359
+ IEmptyableCollection
12360
+ (-empty [coll] (with-meta cljs.core.ObjMap/EMPTY meta))
12361
+
12362
+ IEquiv
12363
+ (-equiv [coll other] (equiv-map coll other))
12364
+
12365
+ IHash
12366
+ (-hash [coll] (hash-coll coll))
12367
+
12368
+ ISeqable
12369
+ (-seq [coll]
12370
+ (when (pos? (.-length keys))
12371
+ (map #(vector % (aget strobj %))
12372
+ (.sort keys obj-map-compare-keys))))
12373
+
12374
+ ICounted
12375
+ (-count [coll] (.-length keys))
12376
+
12377
+ ILookup
12378
+ (-lookup [coll k] (-lookup coll k nil ))
12379
+ (-lookup [coll k not-found]
12380
+ (obj-map-contains-key? k strobj (aget strobj k) not-found))
12381
+
12382
+ IAssociative
12383
+ (-assoc [coll k v]
12384
+ (if (goog/isString k)
12385
+ (let [new-strobj (goog.object/clone strobj)
12386
+ overwrite? (.hasOwnProperty new-strobj k)]
12387
+ (aset new-strobj k v)
12388
+ (if overwrite?
12389
+ (ObjMap. meta keys new-strobj) ; overwrite
12390
+ (let [new-keys (aclone keys)] ; append
12391
+ (.push new-keys k)
12392
+ (ObjMap. meta new-keys new-strobj))))
12393
+ ; non-string key. game over.
12394
+ (with-meta (into (hash-map k v) (seq coll)) meta)))
12395
+ (-contains-key? [coll k]
12396
+ (obj-map-contains-key? k strobj))
12397
+
12398
+ IMap
12399
+ (-dissoc [coll k]
12400
+ (if (and (goog/isString k) (.hasOwnProperty strobj k))
12401
+ (let [new-keys (aclone keys)
12402
+ new-strobj (goog.object/clone strobj)]
12403
+ (.splice new-keys (scan-array 1 k new-keys) 1 )
12404
+ (js-delete new-strobj k)
12405
+ (ObjMap. meta new-keys new-strobj))
12406
+ coll)) ; key not found, return coll unchanged
12407
+
12408
+ IFn
12409
+ (-invoke [coll k]
12410
+ (-lookup coll k))
12411
+ (-invoke [coll k not-found]
12412
+ (-lookup coll k not-found)))
12413
+
12414
+ (set! (. ObjMap -EMPTY) (ObjMap. nil (array ) (js-obj )))
12415
+
12416
+ (set! (. ObjMap -fromObject) (fn [ks obj] (ObjMap. nil ks obj)))
12417
+
12418
+ ; The keys field is an array of all keys of this map, in no particular
12419
+ ; order. Each key is hashed and the result used as a property name of
12420
+ ; hashobj. Each values in hashobj is actually a bucket in order to handle hash
12421
+ ; collisions. A bucket is an array of alternating keys (not their hashes) and
12422
+ ; vals.
12423
+ (deftype HashMap [meta count hashobj]
12424
+ IWithMeta
12425
+ (-with-meta [coll meta] (HashMap. meta count hashobj))
12426
+
12427
+ IMeta
12428
+ (-meta [coll] meta)
12429
+
12430
+ ICollection
12431
+ (-conj [coll entry]
12432
+ (if (vector? entry)
12433
+ (-assoc coll (-nth entry 0 ) (-nth entry 1 ))
12434
+ (reduce -conj
12435
+ coll
12436
+ entry)))
12437
+
12438
+ IEmptyableCollection
12439
+ (-empty [coll] (with-meta cljs.core.HashMap/EMPTY meta))
12440
+
12441
+ IEquiv
12442
+ (-equiv [coll other] (equiv-map coll other))
12443
+
12444
+ IHash
12445
+ (-hash [coll] (hash-coll coll))
12446
+
12447
+ ISeqable
12448
+ (-seq [coll]
12449
+ (when (pos? count)
12450
+ (let [hashes (.sort (js-keys hashobj))]
12451
+ (mapcat #(map vec (partition 2 (aget hashobj %)))
12452
+ hashes))))
12453
+
12454
+ ICounted
12455
+ (-count [coll] count)
12456
+
12457
+ ILookup
12458
+ (-lookup [coll k] (-lookup coll k nil ))
12459
+ (-lookup [coll k not-found]
12460
+ (let [bucket (aget hashobj (hash k))
12461
+ i (when bucket (scan-array 2 k bucket))]
12462
+ (if i
12463
+ (aget bucket (inc i))
12464
+ not-found)))
12465
+
12466
+ IAssociative
12467
+ (-assoc [coll k v]
12468
+ (let [h (hash k)
12469
+ bucket (aget hashobj h)]
12470
+ (if bucket
12471
+ (let [new-bucket (aclone bucket)
12472
+ new-hashobj (goog.object/clone hashobj)]
12473
+ (aset new-hashobj h new-bucket)
12474
+ (if-let [i (scan-array 2 k new-bucket)]
12475
+ (do ; found key, replace
12476
+ (aset new-bucket (inc i) v)
12477
+ (HashMap. meta count new-hashobj))
12478
+ (do ; did not find key, append
12479
+ (.push new-bucket k v)
12480
+ (HashMap. meta (inc count) new-hashobj))))
12481
+ (let [new-hashobj (goog.object/clone hashobj)] ; did not find bucket
12482
+ (aset new-hashobj h (array k v))
12483
+ (HashMap. meta (inc count) new-hashobj)))))
12484
+ (-contains-key? [coll k]
12485
+ (let [bucket (aget hashobj (hash k))
12486
+ i (when bucket (scan-array 2 k bucket))]
12487
+ (if i
12488
+ true
12489
+ false )))
12490
+
12491
+ IMap
12492
+ (-dissoc [coll k]
12493
+ (let [h (hash k)
12494
+ bucket (aget hashobj h)
12495
+ i (when bucket (scan-array 2 k bucket))]
12496
+ (if (not i)
12497
+ coll ; key not found, return coll unchanged
12498
+ (let [new-hashobj (goog.object/clone hashobj)]
12499
+ (if (> 3 (.-length bucket))
12500
+ (js-delete new-hashobj h)
12501
+ (let [new-bucket (aclone bucket)]
12502
+ (.splice new-bucket i 2 )
12503
+ (aset new-hashobj h new-bucket)))
12504
+ (HashMap. meta (dec count) new-hashobj)))))
12505
+
12506
+ IFn
12507
+ (-invoke [coll k]
12508
+ (-lookup coll k))
12509
+ (-invoke [coll k not-found]
12510
+ (-lookup coll k not-found)))
12511
+
12512
+ (set! (. HashMap -EMPTY) (HashMap. nil 0 (js-obj )))
12513
+
12514
+ (set! cljs.core.HashMap/fromArrays (fn [ks vs]
12515
+ (let [len (.-length ks)]
12516
+ (loop [i 0 , out cljs.core.HashMap/EMPTY]
12517
+ (if (< i len)
12518
+ (recur (inc i) (assoc out (aget ks i) (aget vs i)))
12519
+ out)))))
12520
+
12521
+ (deftype Set [meta hash-map]
12522
+ IWithMeta
12523
+ (-with-meta [coll meta] (Set. meta hash-map))
12524
+
12525
+ IMeta
12526
+ (-meta [coll] meta)
12527
+
12528
+ ICollection
12529
+ (-conj [coll o]
12530
+ (Set. meta (assoc hash-map o nil )))
12531
+
12532
+ IEmptyableCollection
12533
+ (-empty [coll] (with-meta cljs.core.Set/EMPTY meta))
12534
+
12535
+ IEquiv
12536
+ (-equiv [coll other]
12537
+ (and
12538
+ (set? other)
12539
+ (= (count coll) (count other))
12540
+ (every? #(contains? coll %)
12541
+ other)))
12542
+
12543
+ IHash
12544
+ (-hash [coll] (hash-coll coll))
12545
+
12546
+ ISeqable
12547
+ (-seq [coll] (keys hash-map))
12548
+
12549
+ ICounted
12550
+ (-count [coll] (count (seq coll)))
12551
+
12552
+ ILookup
12553
+ (-lookup [coll v]
12554
+ (-lookup coll v nil ))
12555
+ (-lookup [coll v not-found]
12556
+ (if (-contains-key? hash-map v)
12557
+ v
12558
+ not-found))
12559
+
12560
+ ISet
12561
+ (-disjoin [coll v]
12562
+ (Set. meta (dissoc hash-map v)))
12563
+
12564
+ IFn
12565
+ (-invoke [coll k]
12566
+ (-lookup coll k))
12567
+ (-invoke [coll k not-found]
12568
+ (-lookup coll k not-found)))
12569
+
12570
+ (set! (. Set -EMPTY) (Set. nil (hash-map )))
0 commit comments