Static for loops

I have a function f(::Val{m}) where m which I want to specialize to a few values. Can I do it in a for loop instead of writing all the specializations by hand?

I tried

for m in 1:3
     f(Val(m))
end

and

for m in (1, 2, 3)
     f(Val(m))
end

but unfortunately both produce type-unstable code.

1 Like

How about using Base.Cartesian.@nexprs?

2 Likes

ntuple(m -> f(Val(m)), Val(3)) should do the trick, I think?

The compiler should eliminate the tuple construction if it is not used. (Still, it might be nice to have a foreach method that accepted a Val for static loops instead of using ntuple for this kind of thing.)

4 Likes

Don’t have a terminal handy, but map works better than loops for stability on tuples. Even better is probably the ntuple function. The below matches your MWE and might be unrolled like you want:
ntuple(i -> f(Val(i)), Val(3))

If not, you can write a macro to manually unroll a loop (or some package probably already has it) for a set of values fixed at compile time.

EDIT: the above beat me to it. Also, the suggested @nexprs is probably easier than a loop unrolling macro, if you decide to go that way.

3 Likes

Thank you. I think @nexprs is the most simple for my use case.

Say my function f is simply f(::Val{m}) where m = println(m). When I execute the line ntuple(m -> f(Val(m)), Val(3)) in the REPL I get

1
2
3
(nothing, nothing, nothing)

Do you mean that the tuple (nothing, nothing, nothing) will be elided by the compiler if not used?

Hi,
I am not sure to understand the type/performance issue of a for loop. Would you kindly explain ?

if the type of
f(Val(m))
is not Int64, is there a performance issue ?

Thanks !

julia> for m in (1, 2, 3)
           println(typeof(m))
       end
Int64
Int64
Int64

The (nothing, nothing, nothing) is the result of the return value from println being run each of 3 times. Yes, the compiler will usually drop these sorts of things if you don’t use them.

That said, this case of (nothing, nothing, nothing) has zero size and is type stable (the compiler knows that println returns nothing and that it’s run 3 times) so it actually only exists within the compiler and the values will never “appear” on your computer’s RAM or processor whether you use them or not.

1 Like