# Generate functions inside a function from string

**URL:** <https://discourse.julialang.org/t/generate-functions-inside-a-function-from-string/12331>\
**Category:** Performance\
**Tags:** question\
**Created:** [July 12, 2018, 1:15pm UTC](https://discourse.julialang.org/t/generate-functions-inside-a-function-from-string/12331 "2018-07-12T13:15:13Z")\
**Posts on this page:** 16\
**Page:** 2

<div class="post-metadata">

**Author:** ![wuhuagumu](https://avatars.discourse-cdn.com/v4/letter/w/7ab992/32.png) [@wuhuagumu](https://discourse.julialang.org/u/wuhuagumu)\
**Post date:** [July 13, 2018, 3:29am UTC](https://discourse.julialang.org/t/generate-functions-inside-a-function-from-string/12331/21 "2018-07-13T03:29:40Z")

</div>

My fault, sorry. I noticed this and forgot to modify it. Changed.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [July 13, 2018, 3:46am UTC](https://discourse.julialang.org/t/generate-functions-inside-a-function-from-string/12331/22 "2018-07-13T03:46:23Z")

</div>

It’s slow and can’t be inlined because it has to do a full dynamic dispatch.

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [July 13, 2018, 4:50am UTC](https://discourse.julialang.org/t/generate-functions-inside-a-function-from-string/12331/23 "2018-07-13T04:50:06Z")

</div>

Just as a note, those functions are fast enough that `@time` is not going to be giving you a reliable or informative benchmark (you’re only running the function once, possibly also measuring compilation time, and you’re operating at global scope, which is slow). [BenchmarkTools.jl](https://github.com/JuliaCI/BenchmarkTools.jl) solves all of those problems for you by running the function multiple times and gathering statistics. In general, `@time` is probably good enough for something which takes a few seconds, but for a function that takes less than a second you really want to use BenchmarkTools.

Using `@btime` from BenchmarkTools:

```julia
julia> using BenchmarkTools

julia> @btime subs($expr, $x => 1.0)
  139.558 μs (79 allocations: 2.34 KiB)
-0.540302305868140

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

julia> @btime $g(1.0)
  115.019 ns (2 allocations: 32 bytes)
-0.5403023058681398

```

> Besides, I thought building something from string should not be a very uncommon thing…

Actually it’s not common in Julia precisely because it’s much easier to manipulate expressions directly in Julia compared to other programming languages. That means that we can treat Julia code as objects in Julia, manipulating or modifying them in code, without ever having to treat them as strings. For example, I can construct the expression `x + y` by quoting it:

```julia
julia> :(x + y)
:(x + y)

```

Or I can construct an Expression type by hand:

```julia
julia> Expr(:call, :+, :x, :y)
:(x + y)

```

and get the same result.

I can also modify an expression to get a new expression:

```julia
julia> ex = Expr(:call, :+, :x, :y)
:(x + y)

julia> ex.args[1] = :- # change that + to a -
:-

julia> ex
:(x - y)

```

In the above case I modified a Julia expression without having to do any string manipulation or invoking of `parse()`.

---

<div class="post-metadata">

**Author:** ![wuhuagumu](https://avatars.discourse-cdn.com/v4/letter/w/7ab992/32.png) [@wuhuagumu](https://discourse.julialang.org/u/wuhuagumu)\
**Post date:** [July 13, 2018, 4:54am UTC](https://discourse.julialang.org/t/generate-functions-inside-a-function-from-string/12331/24 "2018-07-13T04:54:42Z")

</div>

But you have to `eval` these expressions to generate a function. Here my main concern is how to construct a function from expressions without calling `eval`. String is not the most difficult part as `parsing` can do it perfectly.

---

<div class="post-metadata">

**Author:** ![jandehaan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jandehaan/32/6805_2.png) [@jandehaan](https://discourse.julialang.org/u/jandehaan)\
**Post date:** [July 13, 2018, 6:06am UTC](https://discourse.julialang.org/t/generate-functions-inside-a-function-from-string/12331/25 "2018-07-13T06:06:59Z")

</div>

I can’t tell from the discussion what exactly you are trying to accomplish (besides not wanting to use `eval`). But here is a stab in a somewhat different direction.

```julia
macro foo(partial_expr)
    expr = :(x->x)
    expr.args[2] = partial_expr
    expr
end

function bar()
        (@foo(x+2)(3), @foo(x*2)(3), @foo(x^2)(3))
end

```

```julia
julia> bar()
(5, 6, 9)

```

---

<div class="post-metadata">

**Author:** ![Chong\_Wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chong_wang/32/20307_2.png) [@Chong\_Wang](https://discourse.julialang.org/u/Chong_Wang)\
**Post date:** [July 13, 2018, 6:25am UTC](https://discourse.julialang.org/t/generate-functions-inside-a-function-from-string/12331/26 "2018-07-13T06:25:16Z")

</div>

I created a separate thread here summarizing generally what I want:

> [@How do I create a function from an expression](https://discourse.julialang.org/t/how-do-i-create-a-function-from-an-expression/12349):
>
> Suppose I have expr = :(sin(x)+cos(x)) How can I get a function looking like x-\>sin(x)+cos(x) I have tried to write such a macro macro expr2fn(expr, arg) return :($arg -\> $(expr)) end but it does not work julia\> f = @expr2fn expr x (::#63) (generic function with 1 method) julia\> f(1.0) :(sin(x) + cos(x)) Not sure what is happening here.

---

<div class="post-metadata">

**Author:** ![Chong\_Wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chong_wang/32/20307_2.png) [@Chong\_Wang](https://discourse.julialang.org/u/Chong_Wang)\
**Post date:** [July 13, 2018, 8:25am UTC](https://discourse.julialang.org/t/generate-functions-inside-a-function-from-string/12331/28 "2018-07-13T08:25:47Z")

</div>

I believe you posted in the wrong thread. To avoid confusion, I suggest you delete this post and post again in the correct thread: [How do I create a function from an expression - #6 by Chong\_Wang](https://discourse.julialang.org/t/how-do-i-create-a-function-from-an-expression/12349/6)

---

<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:57am UTC](https://discourse.julialang.org/t/generate-functions-inside-a-function-from-string/12331/29 "2018-07-13T09:57:11Z")

</div>

> [@Chong\_Wang](#):
>
> the function produced `f` is type unstable

The type instability is because of the `Base.invokelatest`, if you want to avoid it, you need to specify the output type like this `Base.invokelatest(...)::Float64`, but you already need to know your type.

Would be great if `Base.invokelatest` could be type stable.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [July 13, 2018, 10:06am UTC](https://discourse.julialang.org/t/generate-functions-inside-a-function-from-string/12331/30 "2018-07-13T10:06:25Z")

</div>

> [@chakravala](#):
>
> Would be great if `Base.invokelatest` could be type stable.

The reason why `invokelatest` works at all is also what prevents it to be type stable.

---

<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, 10:24am UTC](https://discourse.julialang.org/t/generate-functions-inside-a-function-from-string/12331/31 "2018-07-13T10:24:02Z")

</div>

> [@Chong\_Wang](#):
>
> the function produced `f` is type unstable?

Alright, so I have fixed this issue with a new implementation of `genfun` in `SyntaxTree` package

```Julia
using SyntaxTree

f = SyntaxTree.genfun(:(-cos(x)), [:(x::Float64)], Float64)

julia> @btime $f(1.0)
  148.596 ns (2 allocations: 32 bytes)
-0.5403023058681398

```

while with the old version I get

```Julia
julia> @btime $f(1.0)
  199.548 ns (2 allocations: 32 bytes)
-0.5403023058681398

```

So there is an improvement by adding the type stability option into `SyntaxTree.genfun`.

```Julia
"""
    genfun(expr, args::Array, typ=Any)

Returns an anonymous function based on the given `expr` and `args`.
"""
function genfun(expr,args::Array,typ=Any)
    gs = gensym()
    eval(Expr(:function,Expr(:call,gs,args...),expr))
    list = Symbol[]
    for arg ∈ args
        push!(list,typeof(arg) == Expr ? arg.args[1] : arg)
    end
    eval(:($(Expr(:tuple,list...))->Base.invokelatest($gs,$(list...))::$typ))
end

```

This now appends `::DataType` at the end of the `Base.invokelatest` call.

---

<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, 10:39am UTC](https://discourse.julialang.org/t/generate-functions-inside-a-function-from-string/12331/32 "2018-07-13T10:39:54Z")

</div>

> [@kristoffer.carlsson](#):
>
> The reason why `invokelatest` works at all is also what prevents it to be type stable.

In my new version of `SyntaxTree.genfun` described in previous post,

```Julia
julia> @code_warntype f(1.0)
Variables:
  #self# <optimized out>
  x::Float64

Body:
  begin 
      return (Core.typeassert)((Core._apply_latest)(SyntaxTree.##713, (Core.tuple)(x::Float64)::Tuple{Float64})::Any, Float64)::Float64
  end::Float64

```

So what is the difference between `Base.invokelatest` and `Core._apply_latest`?

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [July 13, 2018, 10:51am UTC](https://discourse.julialang.org/t/generate-functions-inside-a-function-from-string/12331/33 "2018-07-13T10:51:56Z")

</div>

Let’s rewrite that as

```julia
x = (Core._apply_latest)(SyntaxTree.##713, (Core.tuple)(x::Float64)::Tuple{Float64})::Any
y = (Core.typeassert)(x, Float64)::Float64

```

So `__apply_latest` infers to `Any` and then you have a type assert that errors if the result is not a `Float64` and from there on we can assume that `y` is a `Float64`.

---

<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, 10:56am UTC](https://discourse.julialang.org/t/generate-functions-inside-a-function-from-string/12331/34 "2018-07-13T10:56:19Z")

</div>

Hmmm, after restarting my REPL (was using Revise) the performance for both versions is the same

```nohighlight
julia> g = SyntaxTree.genfun(:x,[:x])

julia> @btime $g(1.0)
  106.034 ns (2 allocations: 32 bytes)
1.0

julia> f = SyntaxTree.genfun(:x,[:(x::Float64)], Float64)
(::#15) (generic function with 1 method)

julia> @btime $f(1.0)
  109.066 ns (2 allocations: 32 bytes)
1.0

```

So it seems that the type assertion for `Any` vs. `Float64` actually does not make a difference, but the new version of `genfun` seems to be faster than the original version anyway…

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [July 13, 2018, 11:01am UTC](https://discourse.julialang.org/t/generate-functions-inside-a-function-from-string/12331/35 "2018-07-13T11:01:26Z")

</div>

The type assert will only be beneficial if you use the result of the function in the same function as it was called.  
Just tacking on a type assert will not make the call itself faster (in fact a bit slower since the type has to be checked).

---

<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, 11:05am UTC](https://discourse.julialang.org/t/generate-functions-inside-a-function-from-string/12331/36 "2018-07-13T11:05:23Z")

</div>

Ah, that makes sense, thanks for clarifying. With `SyntaxTree.genfun` you will have both options.

---

<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:48pm UTC](https://discourse.julialang.org/t/generate-functions-inside-a-function-from-string/12331/37 "2018-07-13T16:48:59Z")

</div>

As discussed in the other thread, in the `SyntaxTree` package there is now an updated `genfun` and `@genfun` for creating functions, and it now does not require `Base.invokelatest`, so is faster

> [@How do I create a function from an expression](https://discourse.julialang.org/t/how-do-i-create-a-function-from-an-expression/12349/21):
>
> 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) -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 i…

[Previous page](https://discourse.julialang.org/t/generate-functions-inside-a-function-from-string/12331.md?page=1)
