Range Over Iterators in Julia
Our example demonstrates how to iterate over structures with support for iterators, including defining custom iterators. Below is the full source code in Julia.
struct Element{T}
val::T
next::Union{Nothing, Element{T}}
end
struct List{T}
head::Union{Nothing, Element{T}}
tail::Union{Nothing, Element{T}}
end
function List{T}() where T
List{T}(nothing, nothing)
end
function push!(lst::List{T}, v::T) where T
if lst.tail === nothing
lst.head = Element{T}(v, nothing)
lst.tail = lst.head
else
lst.tail.next = Element{T}(v, nothing)
lst.tail = lst.tail.next
end
end
function iterate_element(e::Union{Nothing, Element{T}}, state=nothing) where T
return e === nothing ? nothing : (e.val, e.next)
end
function Base.iterate(lst::List{T}, state=nothing) where T
iterate_element(lst.head, state)
end
function gen_fib()
a, b = 1, 1
return () -> begin
val = a
a, b = b, a + b
return val
end
end
In Julia, iterators work with the Base.iterate
function. The example includes a custom linked list and an infinite Fibonacci series generator.
Let’s create a list and push some values into it:
lst = List{Int}()
push!(lst, 10)
push!(lst, 13)
push!(lst, 23)
We can then iterate over the list using a for
loop:
for e in lst
println(e)
end
Julia provides useful packages and functions to work with iterators. Additionally, we demonstrate an infinite Fibonacci sequence generator:
fib = gen_fib()
for n in Iterators.take(fib, 10)
println(n)
end
Running the code will produce the following output:
10
13
23
1
1
2
3
5
8
13
21
This example shows how Julia’s iterator protocol can handle both finite and infinite sequences.
Next example: Errors