# 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 >> 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) >> 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"]] ```