Julia local variable not defined in expression eval
Asked Answered
B

2

6

Given the following function,

function floop(exp)
    a = 5
    b = 10
    ex = Expr(:call, :+, 1, exp);
    return eval(ex);
end

if I then run

floop(Symbol("b"))

I get an error saying that b is not defined. Why does this not work? How can I make this work?

Berenice answered 7/2, 2020 at 1:11 Comment(3)
I would suggest reading up on macros: docs.julialang.org/en/v1/manual/metaprogramming/…Epileptic
@Epileptic Why do you suggest this? Will a macro be able to fulfill this role?Berenice
Yes a macro can do what you want.Epileptic
R
5

One of the key things that lets Julia be fast is that eval always runs in the global scope. This means it can never refer to local variables.

Regenerative answered 7/2, 2020 at 1:27 Comment(0)
A
1

You could do something like the following macro, choosing a value at expansion time, depending on a statically known Symbol:

julia> macro floop(selector::QuoteNode)
           choices = Dict(:a => 5, :b => 10)
           ex = :(1 + $(choices[selector.value]))
           return ex
       end
@floop (macro with 1 method)

julia> @macroexpand @floop(:a)
:(1 + 5)

julia> @macroexpand @floop(:b)
:(1 + 10)

julia> @floop(:c)
ERROR: LoadError: KeyError: key :c not found
Stacktrace:
 [1] getindex(::Dict{Symbol,Int64}, ::Symbol) at ./dict.jl:477
 [2] @floop(::LineNumberNode, ::Module, ::QuoteNode) at ./REPL[27]:3
in expression starting at REPL[33]:1

julia> s = :a; @floop(s)
ERROR: LoadError: MethodError: no method matching @floop(::LineNumberNode, ::Module, ::Symbol)
Closest candidates are:
  @floop(::LineNumberNode, ::Module, ::QuoteNode) at REPL[1]:2
in expression starting at REPL[2]:1

It's up to you how to actually store the actual values. A const global dictionary would be an option, or just a simple if chain.

(There can actually be other things than a Symbol in a QuoteNode, but it's difficult to splice them into the macro call, and they would also just raise a KeyError, so I didn't include any extra handling of that.)

Archeozoic answered 7/2, 2020 at 10:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.