Stream: helpdesk (published)

Topic: ✔ map pattern and avoiding closures


view this post on Zulip Notification Bot (Jul 09 2025 at 14:22):

Alec has marked this topic as resolved.

view this post on Zulip Alec (Jul 09 2025 at 14:27):

I use this pattern so frequently that I'd like to put it in a package for easy use. The macro itself and also reexport the components of MicroCollections.jl and BangBang.jl.

  1. Any concerns with me doing this?
  2. @Mason Protter would you want to 'own' this package and publish it?
  3. Call the package something like MapUnroll?

Mason Protter said:

Of course it's a bit awful to have to write the loop body twice. Sometimes I wish we had a macro @pushalloc for i in 1:n which would expand to something like this -- separate the first iteration, find every push! and allocate space using the first time's types. But I never wrote one.

What I use for stuff like this is an @unroll macro:

macro unroll(N::Int, loop)
    Base.isexpr(loop, :for) || error("only works on for loops")
    Base.isexpr(loop.args[1], :(=)) || error("This loop pattern isn't supported")
    val, itr = esc.(loop.args[1].args)
    body = esc(loop.args[2])
    @gensym loopend
    label = :(@label $loopend)
    goto = :(@goto $loopend)
    out = Expr(:block, :(itr = $itr), :(next = iterate(itr)))
    unrolled = map(1:N) do _
        quote
            isnothing(next) && @goto loopend
            $val, state = next
            $body
            next = iterate(itr, state)
        end
    end
    append!(out.args, unrolled)
    remainder = quote
        while !isnothing(next)
            $val, state = next
            $body
            next = iterate(itr, state)
        end
        @label loopend
    end
    push!(out.args, remainder)
    out
end

view this post on Zulip Mason Protter (Jul 09 2025 at 14:35):

That's a good idea! I don't particularly want to own it, and I'd have no problem with you publishing and owning it. However, if you want we can put it in the JuliaFolds2 organization, and make you a co-owner.


Last updated: Jul 22 2025 at 04:56 UTC