# Creation of function using eval

**URL:** <https://discourse.julialang.org/t/creation-of-function-using-eval/4901>\
**Category:** General Usage\
**Created:** [July 17, 2017, 12:11pm UTC](https://discourse.julialang.org/t/creation-of-function-using-eval/4901 "2017-07-17T12:11:22Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Paethon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paethon/32/9278_2.png) [@Paethon](https://discourse.julialang.org/u/Paethon)\
**Post date:** [July 17, 2017, 12:11pm UTC](https://discourse.julialang.org/t/creation-of-function-using-eval/4901/1 "2017-07-17T12:11:22Z")

</div>

Hi

I have a small problem regarding the dynamic creation of functions from expressions. My situation is the following: A process dynamically generates a random expression which is then evaluated on given samples and an error is calculated with regard to expected outputs. This information is later used to update the creation process for the expressions etc.

Here is what I currently do:

```julia
function run(X, Y, root)
    s = sample(root) #Gives me the random expression
    f = eval(:(x -> $s))
    ev = [Base.invokelatest(f, x) for x in X]
    return mse(ev, Y)
end

```

This works, but the expressions I get are pretty quick to evaluate, so I have the feeling that `invokelatest` adds quite a bit of overhead (Testing for some small functions it seems that `invokelatest` is about 10 times slower than just directly calling a function)

Is this really the best I can do in Julia? I just want to create a local function dynamically. It does not depend on any global things and it only has to be available in this scope, so I am slightly confused why this is made so difficult and also slow.

Or did I just miss something and this can be done in a fundamentally different way?

---

<div class="post-metadata">

**Author:** ![jpiitula](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jpiitula/32/471_2.png) [@jpiitula](https://discourse.julialang.org/u/jpiitula)\
**Post date:** [July 17, 2017, 12:46pm UTC](https://discourse.julialang.org/t/creation-of-function-using-eval/4901/2 "2017-07-17T12:46:44Z")

</div>

What exactly goes wrong if you just invoke the new function?

```julia
    ev = [f(x) for x in X]

```

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [July 17, 2017, 12:48pm UTC](https://discourse.julialang.org/t/creation-of-function-using-eval/4901/3 "2017-07-17T12:48:36Z")

</div>

You can define a function that run the rest of the current function and `invokelast` that.  
And no you can’t do better than that since it’s the most the compiler can infer about your code.

---

<div class="post-metadata">

**Author:** ![Paethon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paethon/32/9278_2.png) [@Paethon](https://discourse.julialang.org/u/Paethon)\
**Post date:** [July 17, 2017, 12:57pm UTC](https://discourse.julialang.org/t/creation-of-function-using-eval/4901/4 "2017-07-17T12:57:05Z")

</div>

I get

```julia
MethodError: no method matching (::##11#12)(::Float64)
The applicable method may be too new: running in world age 31743, while current world is 31744.
Closest candidates are:
  #11(::Any) atptree.jl:205 (method too new to be called from this world context.)
run(::Array{Float64,1}, ::Array{Float64,1}, ::ChoiceNode) at ptree.jl:217
include_string(::String, ::String) at loading.jl:515
eval(::Module, ::Any) at boot.jl:235
...

```

Which seems to be a new restriction introduced in v0.6 (if I understood that correctly(

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [July 17, 2017, 1:05pm UTC](https://discourse.julialang.org/t/creation-of-function-using-eval/4901/5 "2017-07-17T13:05:42Z")

</div>

> [@Paethon](#):
>
> I have the feeling that invokelatest adds quite a bit of overhead

FWIW, since `f` can’t be inferred either on old versions, this is the performance you’ve got on older julia versions all along.

---

<div class="post-metadata">

**Author:** ![Paethon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paethon/32/9278_2.png) [@Paethon](https://discourse.julialang.org/u/Paethon)\
**Post date:** [July 17, 2017, 1:06pm UTC](https://discourse.julialang.org/t/creation-of-function-using-eval/4901/6 "2017-07-17T13:06:09Z")

</div>

Hmm. Yes, that’s what I don’t really get.

I define something like `f = eval(:(x -> x*x+sin(x)))` and then I want to call it on a Float64. So I would just expect that it is then compiled for a Float and executed. The problem does not seem to be that the compiler is not able to infer anything but that Julia just prevents me from calling the function I just created in a normal way.

And it is possible since in Julia v0.5 it works.

But wrapping it in another function and calling that one once using `invokelatest` is probably a reasonable solution.

Thanks

---

<div class="post-metadata">

**Author:** ![Paethon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paethon/32/9278_2.png) [@Paethon](https://discourse.julialang.org/u/Paethon)\
**Post date:** [July 17, 2017, 1:06pm UTC](https://discourse.julialang.org/t/creation-of-function-using-eval/4901/7 "2017-07-17T13:06:45Z")

</div>

OK. So it was just better hidden? Thanks!

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [July 17, 2017, 1:12pm UTC](https://discourse.julialang.org/t/creation-of-function-using-eval/4901/8 "2017-07-17T13:12:35Z")

</div>

It’s not hidden, the function `f` itself is inferred, the caller is not, that also the only difference `invokelatest` has.
