3

In Julia v1.01 I would like to create a function from a string.

Background: In a numerical solver, a testcase is defined via a JSON file. It would be great if the user could specify the initial condition in string form.

This results in the following situation: Assume we have (from the JSON file)

fcn_as_string = "sin.(2*pi*x)" 

Is there a way to convert this into a function fcn such that I can call

fcn(1.0) # = sin.(2*pi*1.0)

Performance is not really an issue, as the initial condition is evaluated once and then the actual computation consumes most of the time.

Thomas
  • 1,199
  • 1
  • 14
  • 29

2 Answers2

6

Can't get my code displayed correctly in a comment so here's a quick fix for crstnbr's solution

function fcnFromString(s)
    f = eval(Meta.parse("x -> " * s))
    return x -> Base.invokelatest(f, x)
end

function main()
    s = "sin.(2*pi*x)"
    f = fcnFromString(s)
    f(1.)
end

julia> main()
-2.4492935982947064e-16
4

The functions Meta.parse and eval allow you to do this:

fcn_as_string = "sin.(2*pi*x)" 
fcn = eval(Meta.parse("x -> " * fcn_as_string))
@show fcn(1.0)

This return -2.4492935982947064e-16 (due to rounding errors).

carstenbauer
  • 9,817
  • 1
  • 27
  • 40
Alex338207
  • 1,825
  • 12
  • 16
  • At first I thought this solves the problem, but I can not put your code in e.g. `main.jl` inside a function. This gives an error: `The applicable method may be too new: running in world age 25050, while current world is 25051.` Any possible modifications? – Thomas Nov 02 '18 at 17:17
  • 1
    You have to pass the arguments by value inside the eval somehow, so the function call gets complete inside the eval. Otherwise the global context generated function finds it has no access to its calling function's local call stack Here is one way: function f(y) fcn_as_string = "sin.(2*pi*x)" @show eval(Meta.parse("(x -> " * fcn_as_string * ")($y)")) end f(1.0) . – Bill Nov 03 '18 at 12:23