Evaluation in calling scope?

it’s because const is missing, see here

so, here’s the solution for calling scope evaluation, despite the fact that only relatively simple expression could be handled:

function expr2fun(ex)
    vars = getvars(ex)
    return eval(:($Expr(:meta, :inline); $vars -> $ex) )   # is it the correct way to inline???
end

getvars(ex) = Expr(:tuple, _getvars(ex)...)
_getvars(ex::Symbol) = [ex]
function _getvars(ex::Expr)
    vars = Symbol[]
    if ex.head == :call
        for arg in ex.args[2:end]
            append!(vars, _getvars(arg) )
        end
    end
    return unique(vars)
end
_getvars(ex) = Symbol[]  # fallback

ex = :(x * (y - x) - (x * y - 2) )
const fun = expr2fun(ex)        # const is needed to avoid warntype !

@inline f1(x, y) = x * (y - x) - (x * y - 2)
@inline f2(x ,y) = fun(x, y)    # calling slope evaluation

julia> f1(1, 2) == f2(1, 2)
true
julia> @btime f1(1, 2);
  0.022 ns (0 allocations: 0 bytes)
julia> @btime f2(1, 2);
  0.022 ns (0 allocations: 0 bytes)
julia> @btime fun(1, 2);
  0.022 ns (0 allocations: 0 bytes)

hope it helps.

1 Like