# Simple, understandable iterator

**URL:** <https://discourse.julialang.org/t/simple-understandable-iterator/124937>\
**Category:** Performance\
**Tags:** question, iterators\
**Created:** [January 20, 2025, 1:24am UTC](https://discourse.julialang.org/t/simple-understandable-iterator/124937 "2025-01-20T01:24:44Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![jlapeyre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlapeyre/32/4514_2.png) [@jlapeyre](https://discourse.julialang.org/u/jlapeyre)\
**Post date:** [January 20, 2025, 1:24am UTC](https://discourse.julialang.org/t/simple-understandable-iterator/124937/1 "2025-01-20T01:24:44Z")

</div>

It’s been noted that a lot of Julia code has more unnecessary allocation and construction of containers than, say, Rust code. I think this is due in large part to Julia’s dual role as a programming language and an application (I probably mentioned this here a while ago.) It’s a bit inconvenient at the REPL to wrap a returned value in collect (after you try to index into it)

Still, I’m trying to do a bit more of this. I’m looking for easy ways to create lazy collections. There are a lot of packages that might help. Generators are easy.

```julia
julia> const v1 = fill(1, 100);
julia> get_numbers1(v) = (float(x) for x in v);

julia> get_numbers1(v1)
Base.Generator{Vector{Int64}, var"#3#4"}(var"#3#4"(), [1, 1, 1, 1, 1, 1, 1, 1, 1, 1 … 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])

```

But as a user, especially a new one, the type of this iterable is confusing, and in fact you can’t see that it returns `Float64`s.

This is a little better.

```julia
julia> get_numbers2(v) = Base.Generator(float, v);

julia> it2 = get_numbers2(v1)
Base.Generator{Vector{Int64}, typeof(float)}(float, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1 … 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])

```

You can look at the docstring for `Generator` to find out what’s happening. But it still has a lot of visual noise. And if I nest a couple of these, the type gets even harder to read. Annotating the return type, or documenting it, is difficult (this happens in Rust, too, but an end user doesn’t typically see it)

I’m considering trying a wrapper:

```julia
struct Iter{T,GT}
    iter::GT
end
@inline Iter{T}(iter) where T = Iter{T, typeof(iter)}(iter)
Base.print(io::IO, ::Iter{T}) where {T} = print(io, "Iter{", T, "}")
Base.show(io::IO, ::MIME"text/plain", iter::Iter) = print(io, iter)
@inline Base.iterate(it::Iter, args...) = iterate(it.iter, args...)
@inline Base.length(it::Iter) = length(it.iter)
@inline Base.eltype(::Iter{T}) where {T} = T

```

Then

```julia
julia> get_numbers3(v) = Iter{Float64}(get_numbers1(v));

julia> it3 = get_numbers3()
Iter{Float64}

```

It’s obvious what this thing returns. They all have equal performance

```julia
julia> @btime sum(it3);
  59.225 ns (0 allocations: 0 bytes)

```

But it’s not very good

```julia
julia> @btime sum(float, v1);
  7.013 ns (0 allocations: 0 bytes)

```

I wonder what kinds of ideas are out there?
