>> >> >> function f(fn!,ar)
>> >> >> for i=1:n
>> >> >> fn!(ar, i) # fn! updates ar[i] somehow, returns nothing
>> >> >> nothing # to make sure output of f is discarded
>> >> >> end
>> >> >> end
>
>
> I'm curious how you would see it optimised? IIUC Julia doesn't know fn! at
> compile time, so it doesn't know if it returns something, or not, so it has
> to allow for a return value even if its to throw it away immediately.
Well it seems Julia should know that nothing is used from fn!, without
knowing anything about fn!. That is at least what @code_warntype
suggest (with julia --inline=no). For
function f(ar)
for i=1:n
hh!(ar, i)
end
end
the loop gives:
GenSym(1) = $(Expr(:call1, :(top(next)), GenSym(0), :(#s1::Int64)))
i = $(Expr(:call1, :(top(getfield)), GenSym(1), 1))
#s1 = $(Expr(:call1, :(top(getfield)), GenSym(1), 2)) # line 71:
$(Expr(:call1, :hh!, :(ar::Array{Float64,1}), :(i::Int64)))
3:
unless $(Expr(:call1, :(top(!)), :($(Expr(:call1, :(top(!)),
:($(Expr(:call1, :(top(done)), GenSym(0), :(#s1::Int64))))))))) goto 2
For
function g(fn!,ar)
a = 0
for i=1:n
fn!(ar, i)
end
a
end
the loop gives:
2:
GenSym(1) = $(Expr(:call1, :(top(next)), GenSym(0), :(#s1::Int64)))
i = $(Expr(:call1, :(top(getfield)), GenSym(1), 1))
#s1 = $(Expr(:call1, :(top(getfield)), GenSym(1), 2)) # line 78:
(fn!::F)(ar::Array{Float64,1},i::Int64)::Any
3:
unless $(Expr(:call1, :(top(!)), :($(Expr(:call1, :(top(!)),
:($(Expr(:call1, :(top(done)), GenSym(0), :(#s1::Int64))))))))) goto 2
So, at least from my naive viewpoint, it looks like there is no need for
an allocation in this case. Or is there ever a case when the return
value of fn! would be used?
I think this is quite different from the case when the return value of
fn! is used because then, as long as Julia cannot do type inference on
the value of fn!, it cannot know what the type is.