How do I create a function from an expression



Actually, I have just figured out to do this macro without Base.invokelatest and updated SyntaxTree :

julia> using SyntaxTree, BenchmarkTools

julia> g = genfun(:(-(cos(x))),[:x])
(::#3) (generic function with 1 method)

julia> @btime $g(1.0)
  40.790 ns (0 allocations: 0 bytes)

julia> f = @genfun -cos(x) [x]
(::#3) (generic function with 1 method)

julia> @btime $f(1.0)
  40.801 ns (0 allocations: 0 bytes)

Now the evaluation is much faster because it is not using Base.invokelatest anymore. The implementation

macro genfun(expr,args)

genfun(expr,args) = :(@genfun $expr [$(args...)]) |> eval

is very simple to write in Julia in the end, it is now part of the SyntaxTree package.

Generate functions inside a function from string

I’d be more convinced if you gave an example of non-use of invokelatest in local scope. We already know that it’s not needed in global scope.

julia> using SyntaxTree

julia> function f(e, t)
           g = genfun(e, [:x])
           return g(t)
f (generic function with 1 method)

julia> f(:(-cos(x)), 1)
ERROR: MethodError: no method matching (::SyntaxTree.##1#2)(::Int64)
The applicable method may be too new: running in world age 21835, while current world is 21836.
Closest candidates are:
  #1(::Any) at /home/gunnar/.julia/v0.6/SyntaxTree/src/SyntaxTree.jl:121 (method too new to be called from this world context.)
 [1] f(::Expr, ::Int64) at ./REPL[2]:3


Indeed, then it’s best to stick to the original method requiring Base.invokelatest and the use of if statements to avoid the use of eval in the anonymous function:

function genfun(expr,args::Array,gs=gensym())
    if length(args) == 0
    elseif length(args) == 1
    elseif length(args) == 2
    elseif length(args) == 3


Okay, so the macro variant of the genfun function can take an arbitrary number of args, while the function variant has to be limited to a finite number by the if statements

macro genfun(expr,args,gs = gensym())