diff --git a/persistent.carp b/persistent.carp index b421ca8..b5abef5 100644 --- a/persistent.carp +++ b/persistent.carp @@ -160,6 +160,17 @@ This generates: (defn to-array [list-ref] (reduce &(fn [acc x] (Array.push-back acc x)) [] list-ref)) + (doc from-array + "Build a list from an `Array`, preserving element order.") + (sig from-array (Fn [(Ref (Array %value-type) q)] %name)) + (defn from-array [arr-ref] + (let-do [acc (empty) + i (- (Array.length arr-ref) 1)] + (while-do (>= i 0) + (set! acc (prepend @(Array.unsafe-nth arr-ref i) &acc)) + (set! i (- i 1))) + acc)) + (doc = "Structural equality: same length and pairwise equal elements.") (sig = (Fn [(Ref %name q) (Ref %name q)] Bool)) (defn = [a-ref b-ref] @@ -394,6 +405,12 @@ This generates: (defn to-array [q-ref] (reduce &(fn [acc x] (Array.push-back acc x)) [] q-ref)) + (doc from-array + "Build a queue from an `Array`, preserving FIFO order.") + (sig from-array (Fn [(Ref (Array %value-type) q)] %name)) + (defn from-array [arr-ref] + (Array.reduce &(fn [acc x] (enqueue @x &acc)) (empty) arr-ref)) + (doc = "Structural equality: same length and pairwise equal FIFO sequence.") (sig = (Fn [(Ref %name q) (Ref %name q)] Bool)) @@ -1090,6 +1107,18 @@ This generates: (defn to-array [trie-ref] (reduce &(fn [acc p] (Array.push-back acc p)) [] trie-ref)) + (doc from-array + "Build a trie from an `Array` of `(Pair key value)` entries.") + (sig from-array + (Fn + [(Ref (Array (Pair (Array %key-part-type) %value-type)) q)] + %name)) + (defn from-array [arr-ref] + (Array.reduce + &(fn [acc p] (insert (Pair.a p) @(Pair.b p) &acc)) + (empty) + arr-ref)) + (doc keys "Collect all keys into an `Array`.") (sig keys (Fn [(Ref %name q)] (Array (Array %key-part-type)))) (defn keys [trie-ref] @@ -1366,6 +1395,12 @@ This generates: (defn to-array [dq-ref] (reduce &(fn [acc x] (Array.push-back acc x)) [] dq-ref)) + (doc from-array + "Build a deque from an `Array`, preserving front-to-back order.") + (sig from-array (Fn [(Ref (Array %value-type) q)] %name)) + (defn from-array [arr-ref] + (Array.reduce &(fn [acc x] (push-back @x &acc)) (empty) arr-ref)) + (doc = "Structural equality: same length and pairwise equal front-to-back sequence.") (sig = (Fn [(Ref %name q) (Ref %name q)] Bool)) @@ -1957,6 +1992,16 @@ This generates: (defn to-array [map-ref] (reduce &(fn [acc p] (Array.push-back acc p)) [] map-ref)) + (doc from-array + "Build an ordered map from an `Array` of `(Pair key value)` entries.") + (sig from-array + (Fn [(Ref (Array (Pair %key-type %value-type)) q)] %name)) + (defn from-array [arr-ref] + (Array.reduce + &(fn [acc p] (insert @(Pair.a p) @(Pair.b p) &acc)) + (empty) + arr-ref)) + (doc keys "Collect keys into an `Array` in ascending order.") (sig keys (Fn [(Ref %name q)] (Array %key-type))) (defn keys [map-ref] @@ -2142,6 +2187,11 @@ Example: (defn to-array [set-ref] (reduce &(fn [acc x] (Array.push-back acc x)) [] set-ref)) + (doc from-array "Build an ordered set from an `Array` of values.") + (sig from-array (Fn [(Ref (Array %value-type) q)] %name)) + (defn from-array [arr-ref] + (Array.reduce &(fn [acc x] (insert @x &acc)) (empty) arr-ref)) + (doc union "Return the union of two sets (all elements from either set).") (sig union (Fn [(Ref %name q) (Ref %name r)] %name)) @@ -2404,6 +2454,11 @@ Example: (defn to-array [heap-ref] (reduce &(fn [acc x] (Array.push-back acc x)) [] heap-ref)) + (doc from-array "Build a heap from an `Array` of values.") + (sig from-array (Fn [(Ref (Array %value-type) q)] %name)) + (defn from-array [arr-ref] + (Array.reduce &(fn [acc x] (insert @x &acc)) (empty) arr-ref)) + (doc any? "Return true if any element satisfies the predicate.") (sig any? (Fn [(Ref (Fn [(Ref %value-type q)] Bool) r) (Ref %name s)] Bool)) @@ -2649,6 +2704,16 @@ Example: (defn to-array [map-ref] (reduce &(fn [acc p] (Array.push-back acc p)) [] map-ref)) + (doc from-array + "Build a hash map from an `Array` of `(Pair key value)` entries.") + (sig from-array + (Fn [(Ref (Array (Pair %key-type %value-type)) q)] %name)) + (defn from-array [arr-ref] + (Array.reduce + &(fn [acc p] (insert @(Pair.a p) @(Pair.b p) &acc)) + (empty) + arr-ref)) + (doc keys "Collect all keys into an `Array`.") (sig keys (Fn [(Ref %name q)] (Array %key-type))) (defn keys [map-ref] @@ -2847,6 +2912,11 @@ Example: (defn to-array [set-ref] (reduce &(fn [acc x] (Array.push-back acc x)) [] set-ref)) + (doc from-array "Build a hash set from an `Array` of values.") + (sig from-array (Fn [(Ref (Array %value-type) q)] %name)) + (defn from-array [arr-ref] + (Array.reduce &(fn [acc x] (insert @x &acc)) (empty) arr-ref)) + (doc union "Return the union of two sets (all elements from either set).") (sig union (Fn [(Ref %name q) (Ref %name r)] %name)) @@ -3031,6 +3101,12 @@ Example: (defn to-array [vec-ref] (reduce &(fn [acc x] (Array.push-back acc x)) [] vec-ref)) + (doc from-array + "Build a vector from an `Array`, preserving index order.") + (sig from-array (Fn [(Ref (Array %value-type) q)] %name)) + (defn from-array [arr-ref] + (Array.reduce &(fn [acc x] (push-back @x &acc)) (empty) arr-ref)) + (doc = "Structural equality: same length and pairwise equal values.") (sig = (Fn [(Ref %name q) (Ref %name q)] Bool)) (defn = [a-ref b-ref] diff --git a/test/persistent_deque.carp b/test/persistent_deque.carp index 9372f29..97afb22 100644 --- a/test/persistent_deque.carp +++ b/test/persistent_deque.carp @@ -246,6 +246,19 @@ (IntDeque.all? &(fn [x] (= x &1)) &(IntDeque.empty)) "all? on empty returns true") + (assert-equal test + true + (let [arr [10 20 30] + d (IntDeque.from-array &arr) + back (IntDeque.to-array &d)] + (= &arr &back)) + "from-array round-trips through to-array") + + (assert-equal test + true + (let [d (IntDeque.from-array &(the (Array Int) []))] (IntDeque.empty? &d)) + "from-array on empty array yields empty deque") + (assert-memory-balance test deque-branch-lifecycle 0l diff --git a/test/persistent_hash_map.carp b/test/persistent_hash_map.carp index 00e1d9e..0685f58 100644 --- a/test/persistent_hash_map.carp +++ b/test/persistent_hash_map.carp @@ -295,6 +295,21 @@ true (IntIntMap.all? &(fn [p] false) &(IntIntMap.empty)) "all? on empty returns true") + (assert-equal test + true + (let [arr [(Pair.init 1 10) (Pair.init 2 20)] + m (IntIntMap.from-array &arr)] + (and (= (IntIntMap.length &m) 2l) + (= &(Maybe.Just 10) &(IntIntMap.get &1 &m)) + (= &(Maybe.Just 20) &(IntIntMap.get &2 &m)))) + "from-array builds map from pairs") + + (assert-equal test + true + (let [m (IntIntMap.from-array &(the (Array (Pair Int Int)) []))] + (IntIntMap.empty? &m)) + "from-array on empty array yields empty map") + (assert-memory-balance test map-branch-lifecycle 0l diff --git a/test/persistent_hash_set.carp b/test/persistent_hash_set.carp index 8ccdafe..ae7d3fa 100644 --- a/test/persistent_hash_set.carp +++ b/test/persistent_hash_set.carp @@ -173,6 +173,21 @@ (IntSet.all? &(fn [x] (= x &1)) &(IntSet.empty)) "all? on empty returns true") + (assert-equal test + true + (let [arr [3 1 2] + s (IntSet.from-array &arr)] + (and (= (IntSet.length &s) 3l) + (IntSet.contains? &3 &s) + (IntSet.contains? &1 &s) + (IntSet.contains? &2 &s))) + "from-array builds set containing all elements") + + (assert-equal test + true + (let [s (IntSet.from-array &(the (Array Int) []))] (IntSet.empty? &s)) + "from-array on empty array yields empty set") + (assert-memory-balance test set-branch-lifecycle 0l diff --git a/test/persistent_heap.carp b/test/persistent_heap.carp index 1beced0..1f5f287 100644 --- a/test/persistent_heap.carp +++ b/test/persistent_heap.carp @@ -147,6 +147,18 @@ (IntHeap.all? &(fn [x] (= x &1)) &(IntHeap.empty)) "all? on empty returns true") + (assert-equal test + true + (let [arr [30 10 20] + h (IntHeap.from-array &arr)] + (and (= (IntHeap.length &h) 3l) (= &(Maybe.Just 10) &(IntHeap.peek &h)))) + "from-array inserts all elements with correct min") + + (assert-equal test + true + (let [h (IntHeap.from-array &(the (Array Int) []))] (IntHeap.empty? &h)) + "from-array on empty array yields empty heap") + (assert-memory-balance test heap-branch-lifecycle 0l diff --git a/test/persistent_list.carp b/test/persistent_list.carp index dcd3570..b354a23 100644 --- a/test/persistent_list.carp +++ b/test/persistent_list.carp @@ -252,6 +252,19 @@ (IntList.all? &(fn [x] (= x &1)) &(IntList.empty)) "all? on empty returns true") + (assert-equal test + true + (let [arr [10 20 30] + l (IntList.from-array &arr) + back (IntList.to-array &l)] + (= &arr &back)) + "from-array round-trips through to-array") + + (assert-equal test + true + (let [l (IntList.from-array &(the (Array Int) []))] (IntList.empty? &l)) + "from-array on empty array yields empty list") + (assert-memory-balance test list-branch-lifecycle 0l diff --git a/test/persistent_ord_map.carp b/test/persistent_ord_map.carp index ebeccab..8845b90 100644 --- a/test/persistent_ord_map.carp +++ b/test/persistent_ord_map.carp @@ -350,6 +350,21 @@ (and (<= (IntIntOMap.height &r) 8) (= (IntIntOMap.length &r) 50l))) "AVL stays balanced after removing half the entries") + (assert-equal test + true + (let [arr [(Pair.init 1 @"one") (Pair.init 2 @"two")] + m (IntStrMap.from-array &arr)] + (and (= (IntStrMap.length &m) 2l) + (= &(Maybe.Just @"one") &(IntStrMap.get 1 &m)) + (= &(Maybe.Just @"two") &(IntStrMap.get 2 &m)))) + "from-array builds map from pairs") + + (assert-equal test + true + (let [m (IntStrMap.from-array &(the (Array (Pair Int String)) []))] + (IntStrMap.empty? &m)) + "from-array on empty array yields empty map") + (assert-memory-balance test map-branch-lifecycle 0l diff --git a/test/persistent_ord_set.carp b/test/persistent_ord_set.carp index f192edb..619988c 100644 --- a/test/persistent_ord_set.carp +++ b/test/persistent_ord_set.carp @@ -183,6 +183,22 @@ (<= (IntSet.height &s) 15)) "AVL set height is logarithmic after 1000 ascending inserts") + (assert-equal test + true + (let [arr [3 1 2] + s (IntSet.from-array &arr) + back (IntSet.to-array &s)] + (and (= (IntSet.length &s) 3l) + (= @(Array.unsafe-nth &back 0) 1) + (= @(Array.unsafe-nth &back 1) 2) + (= @(Array.unsafe-nth &back 2) 3))) + "from-array builds set with elements in ascending order") + + (assert-equal test + true + (let [s (IntSet.from-array &(the (Array Int) []))] (IntSet.empty? &s)) + "from-array on empty array yields empty set") + (assert-memory-balance test set-branch-lifecycle 0l diff --git a/test/persistent_queue.carp b/test/persistent_queue.carp index cafd3fe..98d7297 100644 --- a/test/persistent_queue.carp +++ b/test/persistent_queue.carp @@ -245,6 +245,19 @@ (IntQueue.all? &(fn [x] (= x &1)) &(IntQueue.empty)) "all? on empty returns true") + (assert-equal test + true + (let [arr [10 20 30] + q (IntQueue.from-array &arr) + back (IntQueue.to-array &q)] + (= &arr &back)) + "from-array round-trips through to-array") + + (assert-equal test + true + (let [q (IntQueue.from-array &(the (Array Int) []))] (IntQueue.empty? &q)) + "from-array on empty array yields empty queue") + (assert-memory-balance test queue-branch-lifecycle 0l diff --git a/test/persistent_trie.carp b/test/persistent_trie.carp index 1e1c1b7..3b9a8e5 100644 --- a/test/persistent_trie.carp +++ b/test/persistent_trie.carp @@ -273,6 +273,21 @@ (IntTrieInt.all? &(fn [p] false) &(IntTrieInt.empty)) "all? on empty returns true") + (assert-equal test + true + (let [arr [(Pair.init [1 2] @"a") (Pair.init [3 4] @"b")] + t (IntTrie.from-array &arr)] + (and (= (IntTrie.length &t) 2l) + (= &(Maybe.Just @"a") &(IntTrie.get &[1 2] &t)) + (= &(Maybe.Just @"b") &(IntTrie.get &[3 4] &t)))) + "from-array builds trie from key-value pairs") + + (assert-equal test + true + (let [t (IntTrie.from-array &(the (Array (Pair (Array Int) String)) []))] + (IntTrie.empty? &t)) + "from-array on empty array yields empty trie") + (assert-memory-balance test trie-branch-lifecycle 0l diff --git a/test/persistent_vector.carp b/test/persistent_vector.carp index 079278a..c437771 100644 --- a/test/persistent_vector.carp +++ b/test/persistent_vector.carp @@ -204,6 +204,19 @@ (= &filtered &v2)) "filter with always-true preserves all elements") + (assert-equal test + true + (let [arr [10 20 30] + v (IntVec.from-array &arr) + back (IntVec.to-array &v)] + (= &arr &back)) + "from-array round-trips through to-array") + + (assert-equal test + true + (let [v (IntVec.from-array &(the (Array Int) []))] (IntVec.empty? &v)) + "from-array on empty array yields empty vector") + (assert-memory-balance test vec-branch-lifecycle 0l