But then why is the second example working fine without allocations? Why is there no dynamic dispatch, even though it is the exact same flow of code?
I copy it here (it was in the <details>
tag of the original post):
"""Just some contrived work function that happens to slightly change behavior depending on Val keyword"""
function simple_work_val(obj::Vector; extrawork::Val{B}=Val(true)) where B
l = size(obj,1)
@inbounds for i in 1:l
@inbounds for j in i+1:l
obj[i] ⊻= obj[j]
if B
obj[i] += obj[i]
end
end
end
end
"""A "public interface" function that uses a Bool keyword instead of a Val keyword"""
function simple_work_bool_to_val(obj::Vector; extrawork::Bool=true)
simple_work_val(obj; extrawork=Val(extrawork))
end
The reason for the Val{true}
is that in the real non-minimal case it has noticeably different performance, presumably because it forces specialization. It is something I originally saw in this thread with examples of its use in SciML and Polyester. And here is a real world example where simply switching from Bool to Val{Bool} eliminated allocations, because of this specialization issue - the issue is that this example is rather long so I could not use it as a MWE.