konst/iter/
iter_eval.rs

1/**
2Emulates iterator method chains, by expanding to equivalent code.
3
4For examples that use multiple methods [look here](#full-examples)
5
6# Methods
7
8### Consuming methods
9
10Consuming methods are those that consume the iterator, returning a non-iterator.
11
12The consuming methods listed alphabetically:
13- [`all`](#all)
14- [`any`](#any)
15- [`count`](#count)
16- [`find_map`](#find_map)
17- [`find`](#find)
18- [`fold`](#fold)
19- [`for_each`](#for_each)
20- [`next`](#next)
21- [`nth`](#nth)
22- [`position`](#position)
23- [`rfind`](#rfind)
24- [`rfold`](#rfold)
25- [`rposition`](#rposition)
26
27### Adaptor Methods
28
29Adaptor methods are those that transform the iterator into a different iterator.
30They are shared with other `konst::iter` macros and are documented
31in the  [`iterator_dsl`] module.
32
33The iterator adaptor methods, listed alphabetically
34(these links go to the [`iterator_dsl`] module):
35- [`copied`](./iterator_dsl/index.html#copied)
36- [`enumerate`](./iterator_dsl/index.html#enumerate)
37- [`filter_map`](./iterator_dsl/index.html#filter_map)
38- [`filter`](./iterator_dsl/index.html#filter)
39- [`flat_map`](./iterator_dsl/index.html#flat_map)
40- [`flatten`](./iterator_dsl/index.html#flatten)
41- [`map`](./iterator_dsl/index.html#map)
42- [`rev`](./iterator_dsl/index.html#rev)
43- [`skip_while`](./iterator_dsl/index.html#skip_while)
44- [`skip`](./iterator_dsl/index.html#skip)
45- [`take_while`](./iterator_dsl/index.html#take_while)
46- [`take`](./iterator_dsl/index.html#take)
47- [`zip`](./iterator_dsl/index.html#zip)
48
49
50### `all`
51
52Const equivalent of [`Iterator::all`]
53
54```rust
55use konst::iter;
56const fn all_digits(s: &str) -> bool {
57    iter::eval!(s.as_bytes(),all(|c| matches!(c, b'0'..=b'9')))
58}
59
60assert!(all_digits("123456"));
61assert!(!all_digits("0x123456"));
62
63```
64
65### `any`
66
67Const equivalent of [`Iterator::any`]
68
69
70```rust
71use konst::iter;
72
73const fn contains_pow2(s: &[u64]) -> bool {
74    iter::eval!(s,any(|c| c.is_power_of_two()))
75}
76
77assert!(contains_pow2(&[2, 3, 5]));
78assert!(!contains_pow2(&[13, 21, 34]));
79
80```
81
82### `count`
83
84Const equivalent of [`Iterator::count`]
85
86This example requires the `"rust_1_64"` crate feature,
87because it calls `string::split`.
88
89*/
90#[cfg_attr(not(feature = "rust_1_64"), doc = "```ignore")]
91#[cfg_attr(feature = "rust_1_64", doc = "```rust")]
92/**
93use konst::{iter, string};
94
95const fn count_csv(s: &str) -> usize {
96    iter::eval!(string::split(s, ","),count())
97}
98
99assert_eq!(count_csv("foo"), 1);
100assert_eq!(count_csv("foo,bar"), 2);
101assert_eq!(count_csv("foo,bar,baz"), 3);
102
103```
104
105### `for_each`
106
107Alternative way to write [`konst::iter::for_each`](crate::iter::for_each)
108
109```rust
110use konst::iter;
111
112const fn sum_elems(s: &[u64]) -> u64 {
113    let mut sum = 0u64;
114    iter::eval!{s,copied(),for_each(|x| sum+=x)}
115    sum
116}
117
118assert_eq!(sum_elems(&[]), 0);
119assert_eq!(sum_elems(&[2]), 2);
120assert_eq!(sum_elems(&[3, 5]), 8);
121
122```
123### `next`
124
125Gets the first element in the iterator,
126only needed when intermediate Iterator methods are used.
127
128```rust
129use konst::iter;
130
131const fn first_elem(s: &[u64]) -> Option<u64> {
132    iter::eval!(s,copied(),next())
133}
134
135assert_eq!(first_elem(&[]), None);
136assert_eq!(first_elem(&[2]), Some(2));
137assert_eq!(first_elem(&[3, 5]), Some(3));
138
139```
140
141### `nth`
142
143Const equivalent of [`Iterator::nth`]
144
145This example requires the `"rust_1_64"` crate feature,
146because it calls `string::split`.
147
148*/
149#[cfg_attr(not(feature = "rust_1_64"), doc = "```ignore")]
150#[cfg_attr(feature = "rust_1_64", doc = "```rust")]
151/**
152use konst::{iter, string};
153
154const fn nth_csv(s: &str, nth: usize) -> Option<&str> {
155    iter::eval!(string::split(s, ","),nth(nth))
156}
157
158assert_eq!(nth_csv("foo,bar,baz", 0), Some("foo"));
159assert_eq!(nth_csv("foo,bar,baz", 1), Some("bar"));
160assert_eq!(nth_csv("foo,bar,baz", 2), Some("baz"));
161assert_eq!(nth_csv("foo,bar,baz", 3), None);
162
163```
164
165### `position`
166
167Const equivalent of [`Iterator::position`]
168
169```rust
170use konst::iter;
171
172const fn find_num(slice: &[u64], n: u64) -> Option<usize> {
173    iter::eval!(slice,position(|&elem| elem == n))
174}
175
176assert_eq!(find_num(&[3, 5, 8], 0), None);
177assert_eq!(find_num(&[3, 5, 8], 3), Some(0));
178assert_eq!(find_num(&[3, 5, 8], 5), Some(1));
179assert_eq!(find_num(&[3, 5, 8], 8), Some(2));
180
181```
182
183### `rposition`
184
185Const equivalent of [`Iterator::rposition`]
186
187Limitation: iterator-reversing methods can't be called more than once in 
188the same macro invocation.
189
190```rust
191use konst::iter;
192
193const fn rfind_num(slice: &[u64], n: u64) -> Option<usize> {
194    iter::eval!(slice,rposition(|&elem| elem == n))
195}
196
197assert_eq!(rfind_num(&[3, 5, 8], 0), None);
198assert_eq!(rfind_num(&[3, 5, 8], 3), Some(2));
199assert_eq!(rfind_num(&[3, 5, 8], 5), Some(1));
200assert_eq!(rfind_num(&[3, 5, 8], 8), Some(0));
201
202```
203
204### `find`
205
206Const equivalent of [`Iterator::find`]
207
208```rust
209use konst::iter;
210
211const fn find_odd(slice: &[u64], n: u64) -> Option<&u64> {
212    iter::eval!(slice,find(|&&elem| elem % 2 == 1))
213}
214
215assert_eq!(find_odd(&[], 0), None);
216assert_eq!(find_odd(&[2, 4], 0), None);
217assert_eq!(find_odd(&[3, 5, 8], 3), Some(&3));
218assert_eq!(find_odd(&[8, 12, 13], 3), Some(&13));
219
220```
221
222### `find_map`
223
224Const equivalent of [`Iterator::find_map`]
225
226This example requires the `"parsing_no_proc"` feature.
227
228*/
229#[cfg_attr(not(feature = "parsing_no_proc"), doc = "```ignore")]
230#[cfg_attr(feature = "parsing_no_proc", doc = "```rust")]
231/**
232use konst::{iter, result};
233use konst::primitive::parse_u64;
234
235const fn find_parsable(slice: &[&str]) -> Option<u64> {
236    iter::eval!(slice,find_map(|&s| result::ok!(parse_u64(s))))
237}
238
239assert_eq!(find_parsable(&[]), None);
240assert_eq!(find_parsable(&["foo"]), None);
241assert_eq!(find_parsable(&["foo", "10"]), Some(10));
242assert_eq!(find_parsable(&["10", "20"]), Some(10));
243
244```
245
246### `rfind`
247
248Const equivalent of [`DoubleEndedIterator::rfind`]
249
250Limitation: iterator-reversing methods can't be called more than once in 
251the same macro invocation.
252
253```rust
254use konst::iter;
255
256const fn sum_u64(slice: &[u64]) -> Option<&u64> {
257    iter::eval!(slice,rfind(|&elem| elem.is_power_of_two()))
258}
259
260assert_eq!(sum_u64(&[]), None);
261assert_eq!(sum_u64(&[2]), Some(&2));
262assert_eq!(sum_u64(&[2, 5, 8]), Some(&8));
263
264```
265
266### `fold`
267
268Const equivalent of [`Iterator::fold`]
269
270```rust
271use konst::iter;
272
273const fn sum_u64(slice: &[u64]) -> u64 {
274    iter::eval!(slice,fold(0, |accum, &rhs| accum + rhs))
275}
276
277assert_eq!(sum_u64(&[]), 0);
278assert_eq!(sum_u64(&[3]), 3);
279assert_eq!(sum_u64(&[3, 5]), 8);
280assert_eq!(sum_u64(&[3, 5, 8]), 16);
281
282
283```
284
285### `rfold`
286
287Const equivalent of [`DoubleEndedIterator::rfold`]
288
289Limitation: iterator-reversing methods can't be called more than once in 
290the same macro invocation.
291
292```rust
293use konst::iter;     
294
295const fn concat_u16s(slice: &[u16]) -> u128 {
296    iter::eval!(slice,rfold(0, |accum, &rhs| (accum << 16) + (rhs as u128)))
297}
298
299assert_eq!(concat_u16s(&[1, 2, 3]), 0x0003_0002_0001);
300assert_eq!(concat_u16s(&[3, 5, 8]), 0x0008_0005_0003);
301
302
303```
304
305<span id = "full-examples"></span>
306# Examples
307
308### Second number in CSV
309
310This example demonstrates a function that gets the second number in a CSV string,
311using iterators.
312
313This example requires both the `"parsing_no_proc"` and `"rust_1_64"` features.
314
315*/
316#[cfg_attr(not(all(feature = "parsing_no_proc", feature = "rust_1_64")), doc = "```ignore")]
317#[cfg_attr(all(feature = "parsing_no_proc", feature = "rust_1_64"), doc = "```rust")]
318/**
319use konst::{
320    iter,
321    primitive::parse_u64,
322    result,
323    string,
324};
325
326const fn second_number(s: &str) -> Option<u64> {
327    iter::eval!(
328        string::split(s, ","),
329            filter_map(|s| result::ok!(parse_u64(s))),
330            nth(1),
331    )
332}
333
334assert_eq!(second_number("foo,bar,baz"), None);
335assert_eq!(second_number("foo,3,bar"), None);
336assert_eq!(second_number("foo,3,bar,5"), Some(5));
337assert_eq!(second_number("foo,8,bar,13,baz,21"), Some(13));
338
339```
340
341
342[`iterator_dsl`]: ./iterator_dsl/index.html
343
344*/
345pub use konst_macro_rules::iter_eval as eval;