# Correctly generate function from user input

**URL:** https://discourse.julialang.org/t/correctly-generate-function-from-user-input/29214
**Category:** General Usage
**Tags:** question
**Created:** [September 27, 2019, 3:02am UTC](https://discourse.julialang.org/t/correctly-generate-function-from-user-input/29214 "2019-09-27T03:02:39Z")
**Posts on this page:** 2
**Page:** 1

<div class="post-metadata">

### Author: ![ry-dgel](https://avatars.discourse-cdn.com/v4/letter/r/2acd7d/32.png) [@ry-dgel](https://discourse.julialang.org/u/ry-dgel)
#### Post date: [September 27, 2019, 3:02am UTC](https://discourse.julialang.org/t/correctly-generate-function-from-user-input/29214/1 "2019-09-27T03:02:39Z")

</div>

Hello,

I’m trying to put together a module for rapid fitting of data. I work in an experimental physics lab and want to make a tool that my collegues and I can use to bang out fits of large data sets efficiently.

Ideally I want something of the form:

```julia
fit(xdata, ydata, "sin(a * x) + b", "a = 1, b = 1")

```

Importantly, I want to just be able to pass a string (or expression) that defines the function, as well as the parameters of interest. These two inputs would eventually be turned into a function of the form:

```julia
 func(x, p) = sin.(a * p[1]) .+ p[2])

```

to be handled by LsqFit for the actual fitting.

My initial attempt at this was the following set of functions:

```julia
function parseFunc(fstring::String, params::Vector{Symbol})
    ex = Meta.parse(fstring)
    repExp!(ex, params)
    ex = Meta.parse("@. (x,p) -> $ex")
    return eval(ex)
end

function repExp!(ex::Expr, params::Vector{Symbol})
    for (i, arg) in enumerate(ex.args)
        if arg ∈ params
            pindex = findfirst(isequal(arg), params)
            ex.args[i] = Meta.parse("p[$pindex]")
        elseif arg isa Expr
            repExp!(arg, params)
        end
    end
end

```

However, this lead me to the [world age](https://discourse.julialang.org/t/running-in-world-age-x-while-current-world-is-y-errors/5871) issue that has been discussed multiple times. I understand that I can use `Base.invokelatest() ` but this makes the actual running of the function much slower, and since it has to be evaluated several times over a large data set, this is unnacceptable.

I’ve made several attemps at working around this, but haven’t come up with anything productive. Does anyone have an idea of how I can get this to work in a similar manner of input?

Generally, I’m not worried about safety of the input functions, since the only people using this code will be physicists, but as not all my colleagues use Julia, I very much want the interface of this module to require as close to plain text input of the function as possible.

---

<div class="post-metadata">

### Author: ![ry-dgel](https://avatars.discourse-cdn.com/v4/letter/r/2acd7d/32.png) [@ry-dgel](https://discourse.julialang.org/u/ry-dgel)
#### Post date: [September 27, 2019, 3:07am UTC](https://discourse.julialang.org/t/correctly-generate-function-from-user-input/29214/2 "2019-09-27T03:07:54Z")

</div>

I’ve already read through the following threads, and while giving solid advice, I feel that they don’t entirely apply to my situation, and have yet to tease out a working solution from the information they provide…

> <https://stackoverflow.com/questions/34016768/julia-invoke-a-function-by-a-given-string>

> [@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.

> [@Parsed anonymous functions, type inference, and Base.invokelatest](https://discourse.julialang.org/t/parsed-anonymous-functions-type-inference-and-base-invokelatest/6518):
>
> I have a situation where at some point during runtime a string is parsed and eval’d to an anonymous function, e.g. fa = eval(parse("x -\> mean(x)")) Using Julia v0.5, I could then call fa([1,2,3]) later in the same routine without a problem. In v0.6 however, such a call results in a MethodError mentioning the “world age”. Reading the docs suggests using: Base.invokelatest(fa, [1,2,3]) which works, but, according to the docstrings for invokelatest the type of the output from from the call to f…
