diff --git a/core/Array.carp b/core/Array.carp index 0992696a..4b7e0fed 100644 --- a/core/Array.carp +++ b/core/Array.carp @@ -414,7 +414,32 @@ It will create a copy. If you want to avoid that, consider using [`endo-filter`] (let-do [darr (allocate (StaticArray.length sarr))] (for [i 0 (StaticArray.length sarr)] (aset-uninitialized! &darr i @(StaticArray.unsafe-nth sarr i))) - darr))) + darr)) + + (doc map-reduce "reduces an array `a` by invoking the function `f` on each +element, while keeping an accumulator and a list. + +Returns a `Pair` where the first element is the mapped array and the second one +is the final accumulator. + +The function `f` receives two arguments: the first one is the element, and the +second one is the accumulator. `f` must return `(Pair result accumulator)`. + +Example: +``` +(map-reduce &(fn [acc x] (Pair.init (+ @x @acc) (* @x 2))) 0 &[1 2 3]) +; => (Pair 6 [2 4 6]) +```") + (defn map-reduce [f acc a] + (reduce + &(fn [a el] + (let [l (Pair.b &a) + acc (Pair.a &a) + p (~f acc el)] + (Pair.init @(Pair.a &p) (Array.push-back @l @(Pair.b &p))))) + (Pair.init acc []) + a)) +) (defmacro doall [f xs] `(for [i 0 (Array.length &%xs)] diff --git a/test/array.carp b/test/array.carp index b92b9d46..b8c485f1 100644 --- a/test/array.carp +++ b/test/array.carp @@ -330,5 +330,9 @@ (assert-ref-equal test [1 2 3] (from-static $[1 2 3]) - "from-static works")) - + "from-static works") + (assert-ref-equal test + (Pair.init 6 [2 4 6]) + (map-reduce &(fn [acc x] (Pair.init (+ @x @acc) (* @x 2))) 0 &[1 2 3]) + "map-reduce works") +) diff --git a/test/memory.carp b/test/memory.carp index 026324ab..faeca186 100644 --- a/test/memory.carp +++ b/test/memory.carp @@ -329,6 +329,10 @@ ys (Array.copy-map &str-ref &xs)] (assert (= &[@"1" @"2" @"3" @"4"] &ys)))) +(defn array-map-reduce [] + (let [r (map-reduce &(fn [acc x] (Pair.init (append acc x) (append "-" x))) @"" &[@"1" @"2" @"3"])] + (assert (= &r &(Pair.init @"123" [@"-1" @"-2" @"-3"]))))) + (defn string-append-leak-test [] (let [a "abcdef" b "ghijklmnopqrstuvwxyz"] @@ -487,6 +491,7 @@ (assert-no-leak test array-replicate "array-replicate does not leak") (assert-no-leak test array-copy-map-1 "array-copy-map-1 does not leak") (assert-no-leak test array-copy-map-2 "array-copy-map-2 does not leak") + (assert-no-leak test array-map-reduce "array-map-reduce does not leak") (assert-no-leak test string-append-leak-test "String.append does not leak") (assert-no-leak test lambda-1 "lambda-1 does not leak") (assert-no-leak test lambda-2 "lambda-2 does not leak")