Evaluate expression in function

I have constructed an function like follows:

function f(a::Vector{Float64})
   for i = 1:length(a)
      b = eval(Meta.parse(string("a[",i,"]")))
      println(b)
   end
end

Getting this error when I run test

c = rand(5);

f(c);

UndefVarError: a not defined

eval evaluates in global scope (where you don’t have a):

help?> eval

  eval(expr)

  Evaluate an expression in the global scope of the containing module.
  Every Module (except those defined with baremodule) has its own
  1-argument definition of eval, which evaluates expressions in that
  module.

What are you trying to do? Typically eval(parse(...)) should be avoided, there are probably better ways to do what you want.

2 Likes

I don’t know what you want to do but something like this

b = eval(Meta.parse(string("$(a[i])")))

but for what do you need eval there ?

@mwolff, @fredrikekre Thank you so much for your help.

I am creating a data structure that contains a set of fields

struct point
   x :: Float64
   y :: Float64
   z :: Integer
end

The fields of the structure are used to create expressions.

e.g.

p  = point(1.5,2.5,6)


expr = String[];
push!(expr, "p.x + p.y*5");
push!(expr, "p.x*p.z + p.y*5");
push!(expr, "sin(p.x) + p.y*5");
...

I need to evaluate expressions within a function

values = f(p,expr)

ok this could help a bit

value=Meta.parse("$(sin(p.x) + p.y * 5)")
println(value)

best regards

Michael

Best not to use eval when there’s a much easier way to get what you want:

exprs = Function[]
append!(exprs, [p -> p.x + 5p.y, 
              p -> p.x*p.z + 5p.y,
              p -> sin(p.x) + 5p.y])

p = point(1.5, 2.5, 6)
f(p, exprs) = [expr(p) for expr in exprs]
3 Likes

The main question is why do you need to do that, why do you have to use strings, and why do you need to do that in a function, also what syntax do you want to support. As usual for these kind of question, the solution greately depend on what you actually need.

2 more minor comments,

  1. Don’t use strings, at least use expressions, unless it’s interactive user input (i.e. REPL)

Is not doing any metaprogramming.

1 Like

You are right, for fixed formulas, of course, this is the better way. But if someone sends me a formula over the network as a string and I want a result right away, that’s a possibility. Many roads lead to Rome…

No, for fixed expressions you should have just write that expressions. Turning the result to a string and back doesn’t buy you anything…

then someone will send you a string that evals to a shell on your box.

edit: What you want is a small DSL with robust parser. I don’t know of any good packages that help you with this; but julia macros or eval are not gonna help you here. You should especially prevent contact between the julia parser / deserialization (including jld2) and attacker-supplied data. Even better, ask around whether there are already well-established DSLs supporting the set of features you need, and then write (or import or wrap) a parser for it. After running things through your own parser, you can generate and compile an expression tree if necessary.

@stillyslalom Thank you so much for your help.

The inputs are of type string.
How can I convert string expressions and save them in a function array?

expr_strings = "[p -> p.x + 5p.y, 
                 p -> p.x*p.z + 5p.y,
                 p -> sin(p.x) + 5p.y]"

exprs = include_string(Base, expr_strings)

* edit: it’s better hygiene to work in your own module and reduce risk of a user inadvertently overwriting Base methods, in which case you’d use include_string(MyModule, expr_strings).

3 Likes

Maybe https://github.com/JuliaDiffEq/DiffEqOnlineServer could be a useful starting point (particularly sanitation.jl)