我有一个字符串,例如z[2]
我想在上下文中eval
,例如Dict(:z => 1:10)
最好的方法是什么?
我可以做一些工作,但速度很慢。
function replace_expr(expr, d::Dict)
return expr
end
function replace_expr(s::Symbol, d::Dict)
get(d, s, s)
end
function replace_expr(expr::Expr, d::Dict)
return Expr(replace_expr(expr.head, d),
[replace_expr(e, d) for e in expr.args]...)
end
function eval_with(context::Dict{Symbol, Any}, expr_string::AbstractString)
# E.g. :abc => :(s[:abc])
d = Dict(k => :(s[$(Meta.quot(k))]) for k in keys(context))
ex = parse("s -> $expr_string")
ex = replace_expr(ex, d)
return eval(ex)(context)
end
以下是测试
function make_context()
x = 1
y = "foo"
z = 2:5
Dict(
:x => x,
:y => y,
:z => z
)
end
const context = make_context()
@test eval_with(context, "x + 3") == 4
@test eval_with(context, "string(1, y, 1)") == "1foo1"
@test eval_with(context, "z[2]") == 3
@time eval_with(context, "z[2]")
# 0.004739 seconds (767 allocations: 40.728 KB)
答案 0 :(得分:2)
这似乎是一个可以依靠朱莉娅的内置表达评估机制的地方。 -
采用可选参数:要进行评估的模块。
您可以通过编程方式创建新模块:
eval
您可以使用julia> M = Module()
anonymous
eval
现在,当然,您可以在模块的上下文中评估自定义字符串。
julia> context = Dict(
:x => 1,
:y => "foo",
:z => 2:5
);
julia> for (k,v) in context
eval(M, :($k = $v))
end
julia> M.x
1
julia> M.y
"foo"
像这样的动态评估不会成为朱莉娅闪耀的地方。我认为这将是最好的:
julia> eval(M, parse("x+3"))
4
julia> eval(M, parse("string(1, y, 1)"))
"1foo1"
请注意,这与您上面编写的代码略有不同;您的上下文中的变量仅在开头填充...并且可能会被新的评估更改。
关于使用julia> @time eval(M, parse("z[2]"))
0.000284 seconds (13 allocations: 672 bytes)
3
的{{3}} usual适用。通常还有其他更好的方法来构建您的程序,这些方法将更高效,更易理解,更易于维护。
答案 1 :(得分:2)
如果您事先知道这些值,则可以通过元编程来使用eval。这个的宏由Parameters.jl提供:
d = Dict{Symbol,Any}(:a=>5.0,:b=>2,:c=>"Hi!")
@unpack a, c = d
a == 5.0 #true
c == "Hi!" #true