# How do I create a function from an expression

**URL:** https://discourse.julialang.org/t/how-do-i-create-a-function-from-an-expression/12349
**Category:** General Usage
**Tags:** question
**Created:** [July 13, 2018, 4:38am UTC](https://discourse.julialang.org/t/how-do-i-create-a-function-from-an-expression/12349 "2018-07-13T04:38:40Z")
**Posts on this page:** 4
**Page:** 2

<div class="post-metadata">

### Author: ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)
#### Post date: [July 13, 2018, 4:46pm UTC](https://discourse.julialang.org/t/how-do-i-create-a-function-from-an-expression/12349/21 "2018-07-13T16:46:32Z")

</div>

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

```nohighlight
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)
-0.5403023058681398

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

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

```

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

```nohighlight
macro genfun(expr,args)
    :($(Expr(:tuple,args.args...))->$expr)
end

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

```

is very simple to write in Julia in the end, it is now part of the [SyntaxTree](https://github.com/chakravala/SyntaxTree.jl) package.

---

<div class="post-metadata">

### Author: ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)
#### Post date: [July 13, 2018, 8:38pm UTC](https://discourse.julialang.org/t/how-do-i-create-a-function-from-an-expression/12349/22 "2018-07-13T20:38:27Z")

</div>

> [@chakravala](#):
>
> Actually, I have just figured out to do this macro without `Base.invokelatest` and updated `SyntaxTree` :

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
julia> using SyntaxTree

julia> function f(e, t)
           g = genfun(e, [:x])
           return g(t)
       end
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.)
Stacktrace:
 [1] f(::Expr, ::Int64) at ./REPL[2]:3

```

---

<div class="post-metadata">

### Author: ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)
#### Post date: [July 13, 2018, 9:07pm UTC](https://discourse.julialang.org/t/how-do-i-create-a-function-from-an-expression/12349/23 "2018-07-13T21:07:54Z")

</div>

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:

```nohighlight
function genfun(expr,args::Array,gs=gensym())
    eval(Expr(:function,Expr(:call,gs,args...),expr))
    if length(args) == 0
        ()->Base.invokelatest(eval(gs))
    elseif length(args) == 1
        (a)->Base.invokelatest(eval(gs),a)
    elseif length(args) == 2
        (a,b)->Base.invokelatest(eval(gs),a,b)
    elseif length(args) == 3
        (a,b,c)->Base.invokelatest(eval(gs),a,b,c)
    ...
    end
end

```

---

<div class="post-metadata">

### Author: ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)
#### Post date: [July 13, 2018, 9:16pm UTC](https://discourse.julialang.org/t/how-do-i-create-a-function-from-an-expression/12349/24 "2018-07-13T21:16:36Z")

</div>

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

```nohighlight
macro genfun(expr,args,gs = gensym())
    eval(Expr(:function,Expr(:call,gs,args.args...),expr))
    :($(Expr(:tuple,args.args...))->Base.invokelatest($gs,$(args.args...)))
end

```

[Previous page](https://discourse.julialang.org/t/how-do-i-create-a-function-from-an-expression/12349.md?page=1)
