142 lines
3.2 KiB
Markdown
142 lines
3.2 KiB
Markdown
# Iterators
|
|
|
|
Iterators are one of the most powerful features of the Talc language and
|
|
standard library. An iterator is represented with a zero-argument function.
|
|
Every time the function is called it returns the next item in the sequence,
|
|
or the special value `:end_iteration` to signal that no more items are
|
|
available.
|
|
|
|
An iterator can be created simply by defining such a function:
|
|
|
|
```talc
|
|
>> n = 0
|
|
0
|
|
>> fn counting() do
|
|
if n == 3 then
|
|
return :end_iteration
|
|
end
|
|
n += 1
|
|
n
|
|
end
|
|
<function counting(0) @5661c434f760>
|
|
>> counting()
|
|
1
|
|
>> counting()
|
|
2
|
|
>> counting()
|
|
3
|
|
>> counting()
|
|
:end_iteration
|
|
>> counting()
|
|
:end_iteration
|
|
```
|
|
|
|
Much like lists and ranges, iterators can be used in a `for` loop. In fact,
|
|
lists and ranges are converted to iterators automatically by the `for` loop.
|
|
This can be done manually using the built-in `iter` function:
|
|
|
|
```talc
|
|
>> lst = [2, 3, 5]
|
|
[2, 3, 5]
|
|
>> lst_iter = iter(lst)
|
|
<native function iter[list](0) @5661c4352ef0>
|
|
>> lst_iter()
|
|
2
|
|
>> lst_iter()
|
|
3
|
|
>> lst_iter()
|
|
5
|
|
>> lst_iter()
|
|
:end_iteration
|
|
```
|
|
|
|
An iterator can be converted to a list using the `list` function:
|
|
|
|
```talc
|
|
>> lst = [2, 3, 5]
|
|
[2, 3, 5]
|
|
>> list(iter(lst))
|
|
[2, 3, 5]
|
|
```
|
|
|
|
## Iterator functions
|
|
|
|
The standard library includes many functions to manipulate iterators. Some
|
|
essential ones are listed here. Examples will show both conventional call
|
|
syntax as well as a version using a pipeline.
|
|
|
|
All standard library functions will take the iterator as the final argument.
|
|
|
|
### Map
|
|
|
|
`map` creates a new iterator from an existing one by passing each element
|
|
through a provided function.
|
|
|
|
```talc
|
|
>> list(map(\x -> x^2, [2, 3, 5]))
|
|
[4, 9, 25]
|
|
>> [2, 3, 5] | map(\x -> x^2) | list
|
|
[4, 9, 25]
|
|
```
|
|
|
|
### Filter
|
|
|
|
`filter` creates a new iterator only including values that, when passed to the
|
|
provided function, return a truthy value.
|
|
|
|
```talc
|
|
>> list(filter(\x -> x % 3 != 0, [1, 2, 3, 4, 5, 6]))
|
|
[1, 2, 4, 5]
|
|
>> [1, 2, 3, 4, 5, 6] | filter(\x -> x % 3 != 0) | list
|
|
[1, 2, 4, 5]
|
|
```
|
|
|
|
### Fold
|
|
|
|
`fold` consumes an iterator, applying a two-argument function repeatedly to its
|
|
values.
|
|
|
|
```talc
|
|
>> fold(\x,y -> x*y, [1, 2, 3, 4, 5, 6])
|
|
720
|
|
>> [1, 2, 3, 4, 5, 6] | fold(\x,y -> x*y)
|
|
720
|
|
```
|
|
|
|
`foldi` does the same but allows an initial value to be specified.
|
|
|
|
```talc
|
|
>> foldi(11, \x,y -> x/y, [1, 2, 3, 4, 5, 6])
|
|
720
|
|
>> [1,2,3,4,5,6] | foldi(11, \x,y -> x/y)
|
|
720
|
|
```
|
|
|
|
`sum` and `prod` consume an iterator and return the sum or product of its
|
|
elements, respectively.
|
|
|
|
### Forever and Take
|
|
|
|
`forever` creates an iterator that returns the given value every time it is
|
|
called - an endless iterator. It is useful in combination with `take`, which
|
|
creates an iterator that returns only the first *n* elements of its argument.
|
|
|
|
```talc
|
|
>> list(take(10, forever(42)))
|
|
[42, 42, 42, 42, 42, 42, 42, 42, 42, 42]
|
|
>> forever(42) | take(10) | list
|
|
[42, 42, 42, 42, 42, 42, 42, 42, 42, 42]
|
|
>> forever(42) | list -- bad idea!
|
|
```
|
|
|
|
### Enumerate
|
|
|
|
`enumerate` creates an iterator of two-element arrays, the first is the index
|
|
(starting from `0`) and the second is the item from the original iterator.
|
|
|
|
```
|
|
>> list(enumerate(["a", "b", "c"]))
|
|
[[0, "a"], [1, "b"], [2, "c"]]
|
|
>> ["a", "b", "c"] | enumerate | list
|
|
[[0, "a"], [1, "b"], [2, "c"]]
|
|
```
|