Reputation: 1542
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?
Upvotes: 6
Views: 940
Reputation: 20970
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.)
Upvotes: 1
Reputation: 6398
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.
Upvotes: 5