An Iterator
in Gleam is similar to a list in that it is an ordered collection of values, where all values are of the same type. It differs from a list in that it is lazy, meaning that it does not store all of its values in memory at once, but instead calculates them as they are needed.
This is useful when working with sequences that are very large or even infinite in size, as it allows us to work with them when we do not have enough free memory to store them all at once.
The gleam/iterator
module defines the Iterator
type as well as functions for working with iterators.
Many of the functions for lists also exist for iterators, such as map
, filter
, and take
. These functions return iterators, so the functions do not actually perform any work until the iterator is consumed.
let iter =
[1, 2, 3, 4, 5, 6]
|> iterator.from_list
|> iterator.filter(fn(x) { x > 2 })
|> iterator.take(2)
// No work has been done yet as the iterator has not been consumed
// Consume the iterator and collect the values into a list
iterator.to_list(iter)
// -> [3, 4]
The unfold
function can be used to create iterators from a function that is called repeatedly to produce the next value in the sequence.
Here the unfold
function is used to create an iterator that produces the Fibonacci sequence:
iterator.unfold(#(0, 1), fn(pair) {
let x = pair.0 + pair.1
iterator.Next(element: x, accumulator: #(pair.1, x))
})
|> iterator.take(6)
|> iterator.to_list
// -> [1, 2, 3, 5, 8, 13]
The sequence here is infinite, so the take
function is used to make it finite before collecting the values into a list. If to_list
is called on an infinite iterator the program will run until the program runs out of memory and crashes.
Alizé runs an online fashion boutique. The big annual sale is coming up, so she wants to create some functionality to help take stock of the inventory.
A single item in the inventory is represented using a custom type.
Item(
name: "White Shirt",
price: 40,
quantity: 6,
)
Implement item_names
function, which takes an iterator of items and returns an iterator of their names in the same order.
[
Item(price: 65, name: "Maxi Brown Dress", quantity: 8),
Item(price: 50, name: "Red Short Skirt", quantity: 0),
Item(price: 29, name: "Black Short Skirt", quantity: 4),
Item(price: 20, name: "Bamboo Socks Cats", quantity: 7),
]
|> iterator.from_list
|> item_names
|> iterator.to_list
// -> ["Maxi Brown Dress", "Red Short Skirt", "Black Short Skirt", "Bamboo Socks Cats"]
Implement the cheap
function, which takes an iterator of items and returns an iterator of items that cost less than 30.
[
Item(price: 65, name: "Maxi Brown Dress", quantity: 8),
Item(price: 50, name: "Red Short Skirt", quantity: 0),
Item(price: 29, name: "Black Short Skirt", quantity: 4),
Item(price: 20, name: "Bamboo Socks Cats", quantity: 7),
]
|> iterator.from_list
|> cheap
|> iterator.to_list
// -> [
// Item(price: 29, name: "Black Short Skirt", quantity: 4),
// Item(price: 20, name: "Bamboo Socks Cats", quantity: 7),
// ]
Implement the out_of_stock
function which returns any items that have no stock.
[
Item(price: 65, name: "Maxi Brown Dress", quantity: 8),
Item(price: 50, name: "Red Short Skirt", quantity: 0),
Item(price: 29, name: "Black Short Skirt", quantity: 4),
Item(price: 20, name: "Bamboo Socks Cats", quantity: 7),
]
|> iterator.from_list
|> out_of_stock
|> iterator.to_list
// -> [
// Item(price: 50, name: "Red Short Skirt", quantity: 0),
// ]
Implement the total_stock
function which calculates the total amount of items in your storeroom:
[
Item(price: 65, name: "Maxi Brown Dress", quantity: 8),
Item(price: 50, name: "Red Short Skirt", quantity: 0),
Item(price: 29, name: "Black Short Skirt", quantity: 4),
Item(price: 20, name: "Bamboo Socks Cats", quantity: 7),
]
|> iterator.from_list
|> total_stock
// -> 19
Sign up to Exercism to learn and master Gleam with 36 concepts, 125 exercises, and real human mentoring, all for free.