Julia has a generator syntax that works as follows.
julia> f(x) = x^2
f (generic function with 1 method)
julia> gen = (f(x) for x in 1:5)
Base.Generator{UnitRange{Int64}, var"#1#2"}(var"#1#2"(), 1:5)
julia> for y in gen
println(y)
end
1
4
9
16
25
We can apply it to the original problem by adding a conditional statement.
julia> x = [1,3,2,4,9,8,7,6,5];
julia> gen = (k => v for (k,v) in pairs(x) if v % 2 == 1)
Base.Generator{Base.Iterators.Filter{var"#4#6", Base.Pairs{Int64, Int64, LinearIndices{1, Tuple{Base.OneTo{Int64}}}, Vector{Int64}}}, var"#3#5"}(var"#3#5"(), Base.Iterators.Filter{var"#4#6", Base.Pairs{Int64, Int64, LinearIndices{1, Tuple{Base.OneTo{Int64}}}, Vector{Int64}}}(var"#4#6"(), Base.Pairs(1 => 1, 2 => 3, 3 => 2, 4 => 4, 5 => 9, 6 => 8, 7 => 7, 8 => 6, 9 => 5)))
julia> for (k,v) in gen
println(k, "\t", v)
end
1 1
2 3
5 9
7 7
9 5
Essentially what we are doing is wrapping our desired function in a Base.Generator
. Note that in general, Julia iterators are usually stateless. That is we can iterate through the generator multiple times.
julia> for (k,v) in gen
println(k, "\t", v)
end
1 1
2 3
5 9
7 7
9 5
julia> for (k,v) in gen
println(k, "\t", v)
end
1 1
2 3
5 9
7 7
9 5
julia> for (k,v) in gen
println(k, "\t", v)
end
1 1
2 3
5 9
7 7
9 5
julia> for (k,v) in gen
println(k, "\t", v)
end
1 1
2 3
5 9
7 7
9 5
Something helpful to you might be an adaptor from Lua to Julia.
julia> struct LuaGenerator{F}
f::F
end
julia> function Base.iterate(lg::LuaGenerator, _=nothing)
r = lg.f()
isnothing(r) ? nothing : (r, nothing)
end
julia> for (k,v) in LuaGenerator(godd(x))
println(k, "\t", v)
end
1 1
2 3
5 9
7 7
9 5
julia> for (k,v) in LuaGenerator(godd(x))
println(k, "\t", v)
end
1 1
2 3
5 9
7 7
9 5
julia> gen = LuaGenerator(godd(x))
LuaGenerator{var"#7#8"{Vector{Int64}}}(var"#7#8"{Vector{Int64}}([1, 3, 2, 4, 9, 8, 7, 6, 5], Core.Box(1)))
julia> for (k,v) in gen
println(k, "\t", v)
end
1 1
2 3
5 9
7 7
9 5
julia> for (k,v) in gen # this generator is stateful
println(k, "\t", v)
end