Skip to content

Commit 320bc67

Browse files
authored
feat: scan functions (#1339)
1 parent 643efd5 commit 320bc67

File tree

4 files changed

+59
-1
lines changed

4 files changed

+59
-1
lines changed

core/Array.carp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,30 @@ It will sum the previous sum with each new value, starting at `0`.")
4343
(set! total (~f total (unsafe-nth xs i))))
4444
total)))
4545

46+
(doc scan "Similar to `Array.reduce`, but instead returns an array with the starting element,
47+
and then all intermediate values.
48+
49+
For example, a scan using `Int.+` over the array [1 1 1 1 1] (starting at 0) will return [0 1 2 3 4 5].")
50+
(defn scan [f x xs]
51+
(let [n (length xs)
52+
ys (allocate (inc n))]
53+
(do
54+
(aset-uninitialized! &ys 0 @&x)
55+
(for [i 1 (inc n)]
56+
(aset-uninitialized! &ys i (~f (unsafe-nth &ys (dec i)) (unsafe-nth xs (dec i)))))
57+
ys)))
58+
59+
(doc endo-scan "Like `Array.scan`, but uses the first element of the array as the starting value.
60+
Also does not create a new array, but reuses the initial one instead (by taking ownership over `xs`.)
61+
62+
For example, an endo-scan using `Int.+` over the array [1 1 1 1 1] will return [1 2 3 4 5]")
63+
(defn endo-scan [f xs]
64+
(let [n (length &xs)]
65+
(do
66+
(for [i 1 n]
67+
(aset! &xs i (~f (unsafe-nth &xs (dec i)) (unsafe-nth &xs i))))
68+
xs)))
69+
4670
(doc empty? "checks whether the array `a` is empty.")
4771
(defn empty? [a]
4872
(= (Array.length a) 0))

core/StaticArray.carp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ stack-allocated. For a more flexible, heap-allocated version, you might want to
3838
(set! total (~f total (StaticArray.unsafe-nth xs i))))
3939
total)))
4040

41+
(doc scan! "Scans and replaces the array in-place, using a binary function.
42+
43+
For example, give `(def numbers [1 1 1])`, a `scan!` using `Int.+` will mutate `numbers` to be `[1 2 3]`.")
44+
(defn scan! [f xs]
45+
(let [n (StaticArray.length xs)]
46+
(for [i 1 n]
47+
(StaticArray.aset! xs i (~f @(unsafe-nth xs (dec i)) @(unsafe-nth xs i))))))
48+
4149
(doc = "compares two static arrays.")
4250
(defn = [a b]
4351
(if (/= (StaticArray.length a) (StaticArray.length b))

test/array.carp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,4 +335,20 @@
335335
(Pair.init 6 [2 4 6])
336336
(map-reduce &(fn [acc x] (Pair.init (+ @x @acc) (* @x 2))) 0 &[1 2 3])
337337
"map-reduce works")
338+
(assert-ref-equal test
339+
[0 1 2 3 4 5]
340+
(scan &(fn [x y] (+ @x @y)) 0 &[1 1 1 1 1])
341+
"scan works")
342+
(assert-ref-equal test
343+
[@"" @"a" @"ab" @"abc"]
344+
(Array.scan &(fn [a b] (String.append a b)) @"" &[@"a" @"b" @"c"])
345+
"scan works on managed type")
346+
(assert-ref-equal test
347+
[1 2 3 4 5]
348+
(endo-scan &(fn [x y] (+ @x @y)) [1 1 1 1 1])
349+
"endo-scan works")
350+
(assert-ref-equal test
351+
[@"a" @"ab" @"abc"]
352+
(Array.endo-scan &String.append [@"a" @"b" @"c"])
353+
"endo-scan works on managed type")
338354
)

test/static_array.carp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,4 +216,14 @@
216216
(assert-equal test
217217
&2
218218
(Pointer.to-ref (Pointer.inc (unsafe-raw $[1 2 3])))
219-
"unsafe-raw works as expected II"))
219+
"unsafe-raw works as expected II")
220+
221+
(let [arr $[1 1 1 1 1]]
222+
(assert-equal test
223+
$[1 2 3 4 5]
224+
(do
225+
(StaticArray.scan! &Int.+ arr)
226+
arr)
227+
"scan! works"))
228+
229+
)

0 commit comments

Comments
 (0)