Frames Catherine White
Frames Catherine White

Reputation: 28192

Why does Julia have `Base.invokelatest`?

It seems like it just calls the function. When is it needed? It seems much slower than calling the function directly.

Upvotes: 6

Views: 1286

Answers (1)

Frames Catherine White
Frames Catherine White

Reputation: 28192

Consider the following example, Where a function bar uses @eval to redefine foo before calling it

julia> foo() = 1
foo (generic function with 2 methods)

julia> function bar()
           @eval foo() = 2  # remember @eval runs at global scope
           foo()
       end
bar (generic function with 1 method)

julia> bar()
1   # Got old version

julia> function bar2()
           @eval foo() = 3  # remember @eval runs at global scope
           Base.invokelatest(foo,)
       end
bar2 (generic function with 1 method)

julia> bar2()
3

Because by the time bar calls foo bar has by its nature already been compiled, and so foo has been optimized as a static call. (probably inlined even in this case).

So bar can’t see the newly overwritten foo that was created via @eval

It is slower because it prevents the call compiling down to a static dispatch.

Generally you should never need this This kinda code is not good. Try and avoid using @eval inside functions. It is hard to reason about.

Upvotes: 13

Related Questions