Skip to content

Commit 24e2217

Browse files
chore: add mapi/for_eachi functions (#7705)
1 parent b059fd1 commit 24e2217

File tree

7 files changed

+583
-0
lines changed

7 files changed

+583
-0
lines changed

cspell.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
"desugared",
8989
"devcontainer",
9090
"direnv",
91+
"eachi",
9192
"eddsa",
9293
"elab",
9394
"Elligator",
@@ -143,6 +144,7 @@
143144
"losslessly",
144145
"lvalue",
145146
"Maddiaa",
147+
"mapi",
146148
"mathbb",
147149
"memfs",
148150
"memset",

docs/docs/noir/concepts/data_types/arrays.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,65 @@ let a = [1, 2, 3];
164164
let b = a.map(|a| a * 2); // b is now [2, 4, 6]
165165
```
166166

167+
### mapi
168+
169+
Applies a function to each element of the array, along with its index in the
170+
array, returning a new array containing the mapped elements.
171+
172+
```rust
173+
fn mapi<U, Env>(self, f: fn[Env](u32, T) -> U) -> [U; N]
174+
```
175+
176+
example
177+
178+
```rust
179+
let a = [1, 2, 3];
180+
let b = a.mapi(|i, a| i + a * 2); // b is now [2, 5, 8]
181+
```
182+
183+
### for_each
184+
185+
Applies a function to each element of the array.
186+
187+
```rust
188+
fn for_each<Env>(self, f: fn[Env](T) -> ())
189+
```
190+
191+
example
192+
193+
```rust
194+
let a = [1, 2, 3];
195+
a.for_each(|x| {
196+
println(f"{x}");
197+
});
198+
// prints:
199+
// 1
200+
// 2
201+
// 3
202+
```
203+
204+
### for_eachi
205+
206+
Applies a function to each element of the array, along with its index in the
207+
array.
208+
209+
```rust
210+
fn for_eachi<Env>(self, f: fn[Env](u32, T) -> ())
211+
```
212+
213+
example
214+
215+
```rust
216+
let a = [1, 2, 3];
217+
a.for_eachi(|i, x| {
218+
println(f"{i}, {x}");
219+
});
220+
// prints:
221+
// 0, 1
222+
// 1, 2
223+
// 2, 3
224+
```
225+
167226
### fold
168227

169228
Applies a function to each element of the array, returning the final accumulated value. The first

docs/docs/noir/concepts/data_types/slices.mdx

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,65 @@ let a = &[1, 2, 3];
207207
let b = a.map(|a| a * 2); // b is now &[2, 4, 6]
208208
```
209209

210+
### mapi
211+
212+
Applies a function to each element of the slice, along with its index in the
213+
slice, returning a new slice containing the mapped elements.
214+
215+
```rust
216+
fn mapi<U, Env>(self, f: fn[Env](u32, T) -> U) -> [U]
217+
```
218+
219+
example
220+
221+
```rust
222+
let a = &[1, 2, 3];
223+
let b = a.mapi(|i, a| i + a * 2); // b is now &[2, 5, 8]
224+
```
225+
226+
### for_each
227+
228+
Applies a function to each element of the slice.
229+
230+
```rust
231+
fn for_each<Env>(self, f: fn[Env](T) -> ())
232+
```
233+
234+
example
235+
236+
```rust
237+
let a = &[1, 2, 3];
238+
a.for_each(|x| {
239+
println(f"{x}");
240+
});
241+
// prints:
242+
// 1
243+
// 2
244+
// 3
245+
```
246+
247+
### for_eachi
248+
249+
Applies a function to each element of the slice, along with its index in the
250+
slice.
251+
252+
```rust
253+
fn for_eachi<Env>(self, f: fn[Env](u32, T) -> ())
254+
```
255+
256+
example
257+
258+
```rust
259+
let a = &[1, 2, 3];
260+
a.for_eachi(|i, x| {
261+
println(f"{i}, {x}");
262+
});
263+
// prints:
264+
// 0, 1
265+
// 1, 2
266+
// 2, 3
267+
```
268+
210269
### fold
211270

212271
Applies a function to each element of the slice, returning the final accumulated value. The first

docs/docs/noir/standard_library/containers/boundedvec.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,43 @@ Example:
294294

295295
#include_code bounded-vec-map-example noir_stdlib/src/collections/bounded_vec.nr rust
296296

297+
### mapi
298+
299+
```rust
300+
pub fn mapi<U, Env>(self, f: fn[Env](u32, T) -> U) -> BoundedVec<U, MaxLen>
301+
```
302+
303+
Creates a new vector of equal size by calling a closure on each element in this
304+
vector, along with its index in the vector.
305+
306+
Example:
307+
308+
#include_code bounded-vec-mapi-example noir_stdlib/src/collections/bounded_vec.nr rust
309+
310+
### for_each
311+
312+
```rust
313+
pub fn for_each<Env>(self, f: fn[Env](T) -> ())
314+
```
315+
316+
Calls a closure on each element in this vector.
317+
318+
Example:
319+
320+
#include_code bounded-vec-for-each-example noir_stdlib/src/collections/bounded_vec.nr rust
321+
322+
### for_eachi
323+
324+
```rust
325+
pub fn for_eachi<Env>(self, f: fn[Env](u32, T) -> ())
326+
```
327+
328+
Calls a closure on each element in this vector, along with its index in the vector.
329+
330+
Example:
331+
332+
#include_code bounded-vec-for-eachi-example noir_stdlib/src/collections/bounded_vec.nr rust
333+
297334
### any
298335

299336
```rust

noir_stdlib/src/array/mod.nr

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,65 @@ impl<T, let N: u32> [T; N] {
5353
ret
5454
}
5555

56+
/// Applies a function to each element of this array along with its index,
57+
/// returning a new array containing the mapped elements.
58+
///
59+
/// Example:
60+
///
61+
/// ```rust
62+
/// let a = [1, 2, 3];
63+
/// let b = a.mapi(|i, a| i + a * 2);
64+
/// assert_eq(b, [2, 5, 8]);
65+
/// ```
66+
pub fn mapi<U, Env>(self, f: fn[Env](u32, T) -> U) -> [U; N] {
67+
let uninitialized = crate::mem::zeroed();
68+
let mut ret = [uninitialized; N];
69+
70+
for i in 0..self.len() {
71+
ret[i] = f(i, self[i]);
72+
}
73+
74+
ret
75+
}
76+
77+
/// Applies a function to each element of this array.
78+
///
79+
/// Example:
80+
///
81+
/// ```rust
82+
/// let a = [1, 2, 3];
83+
/// let mut b = [0; 3];
84+
/// let mut i = 0;
85+
/// a.for_each(|x| {
86+
/// b[i] = x;
87+
/// i += 1;
88+
/// });
89+
/// assert_eq(a, b);
90+
/// ```
91+
pub fn for_each<Env>(self, f: fn[Env](T) -> ()) {
92+
for i in 0..self.len() {
93+
f(self[i]);
94+
}
95+
}
96+
97+
/// Applies a function to each element of this array along with its index.
98+
///
99+
/// Example:
100+
///
101+
/// ```rust
102+
/// let a = [1, 2, 3];
103+
/// let mut b = [0; 3];
104+
/// a.for_eachi(|i, x| {
105+
/// b[i] = x;
106+
/// });
107+
/// assert_eq(a, b);
108+
/// ```
109+
pub fn for_eachi<Env>(self, f: fn[Env](u32, T) -> ()) {
110+
for i in 0..self.len() {
111+
f(i, self[i]);
112+
}
113+
}
114+
56115
/// Applies a function to each element of the array, returning the final accumulated value. The first
57116
/// parameter is the initial value.
58117
///
@@ -256,6 +315,61 @@ mod test {
256315
assert_eq([].map(|x| x + 1), []);
257316
}
258317

318+
#[test]
319+
fn mapi_empty() {
320+
assert_eq([].mapi(|i, x| i * x + 1), []);
321+
}
322+
323+
#[test]
324+
fn for_each_empty() {
325+
let empty_array: [Field; 0] = [];
326+
empty_array.for_each(|_x| assert(false));
327+
}
328+
329+
#[test]
330+
fn for_eachi_empty() {
331+
let empty_array: [Field; 0] = [];
332+
empty_array.for_eachi(|_i, _x| assert(false));
333+
}
334+
335+
#[test]
336+
fn map_example() {
337+
let a = [1, 2, 3];
338+
let b = a.map(|a| a * 2);
339+
assert_eq(b, [2, 4, 6]);
340+
}
341+
342+
#[test]
343+
fn mapi_example() {
344+
let a = [1, 2, 3];
345+
let b = a.mapi(|i, a| i + a * 2);
346+
assert_eq(b, [2, 5, 8]);
347+
}
348+
349+
#[test]
350+
fn for_each_example() {
351+
let a = [1, 2, 3];
352+
let mut b = [0, 0, 0];
353+
let b_ref = &mut b;
354+
let mut i = 0;
355+
let i_ref = &mut i;
356+
a.for_each(|x| {
357+
b_ref[*i_ref] = x * 2;
358+
*i_ref += 1;
359+
});
360+
assert_eq(b, [2, 4, 6]);
361+
assert_eq(i, 3);
362+
}
363+
364+
#[test]
365+
fn for_eachi_example() {
366+
let a = [1, 2, 3];
367+
let mut b = [0, 0, 0];
368+
let b_ref = &mut b;
369+
a.for_eachi(|i, a| { b_ref[i] = i + a * 2; });
370+
assert_eq(b, [2, 5, 8]);
371+
}
372+
259373
#[test]
260374
fn concat() {
261375
let arr1 = [1, 2, 3, 4];

0 commit comments

Comments
 (0)