nathanielng
nathanielng

Reputation: 1725

In Julia, is it possible to pass values for evaluation in an Expr object without using global variables?

I'd like to be able to convert a string expression, e.g. "2.0*x*log(x)", to a function in Julia. The usual way to do pass the value of "x" would be through global variables:

julia> func1 = parse("2.0*x*log(x)");
julia> x = 2.718281828459;
julia> eval(func1)/2.0
2.7182818284589545

However, I'd like to know if I can avoid using global variables. I've tried the following two methods, but was not successful:

Method 1

julia> func2(x) = parse("2.0*x*log(x)");
julia> eval(func2(1.0))/2.0  # should return zero
2.7182818284589545

Method 2

julia> function new_func1(input_value)
           x = input_value
           eval(func1)
       end
new_func1 (generic function with 1 method)

julia> new_func1(1.0)/2.0  # should return zero
2.7182818284589545

Upvotes: 1

Views: 493

Answers (3)

nathanielng
nathanielng

Reputation: 1725

It appears it's also possible to use @generated to do this:

string = "2.0*x*log(x)"
@generated function my_func(x)
    return parse(string)
end

Sample output:

julia> println(my_func(1.0))
0.0

julia> println(my_func(exp(1.0))/2.0)
2.718281828459045

julia> println(my_func(0.5))
-0.6931471805599453

Thinking about this further, perhaps it would have been better to use the dot notation for multiplication:

string = "2.0.*x.*log(x)"
@generated function my_func(x)
    return parse(string)
end

julia> x = [1.0 0.5 exp(1.0)]
1x3 Array{Float64,2}:
 1.0  0.5  2.71828

julia> my_func(x)
1x3 Array{Float64,2}:
 0.0  -0.693147  5.43656

Upvotes: 0

Daniel Arndt
Daniel Arndt

Reputation: 2543

With func2, since you're not interpolating x within the function, the expression is being built with just symbol x. This is falling back to your global x you set when writing func1.

Try this:

julia> func2(x) = parse("2.0*$x*log($x)");

julia> eval(func2(1.0))
0.0

Or, alternatively,

julia> func2(x) = eval(parse("2.0*$x*log($x)"));

julia> func2(1.0)
0.0

Upvotes: 0

jfish003
jfish003

Reputation: 1332

How about doing this:

    ex = parse(string)
    @eval f(x) = $ex

When I plugged in your string and the number 1 it returned 0, 2 returned 2.772588 and so on.

Upvotes: 4

Related Questions