从Julia中的字典以编程方式创建局部变量

从Julia中的字典以编程方式创建局部变量,julia,julia-jump,Julia,Julia Jump,考虑以下功能: function func(vars::Dict{Symbol, Any}) end 我想在func的作用域中创建局部变量, 哪里: 变量名分别是变量的键和 变量值是与给定键对应的vars中的值 我知道我可以在以下内容中使用eval(): for (k, v) in vars eval(:($k = $v)) end 但是,这将在全局范围内定义变量,这会对性能产生影响,并可能覆盖现有的全局变量 顺便说一下,如果你的建议与我要采用的方法有很大不同,我会添加一个上下文。

考虑以下功能:

function func(vars::Dict{Symbol, Any})

end
我想在
func
的作用域中创建局部变量, 哪里: 变量名分别是
变量的键
和 变量值是与给定键对应的
vars
中的值

我知道我可以在以下内容中使用
eval()

for (k, v) in vars
    eval(:($k = $v))
end
但是,这将在全局范围内定义变量,这会对性能产生影响,并可能覆盖现有的全局变量


顺便说一下,如果你的建议与我要采用的方法有很大不同,我会添加一个上下文。我正在实现一个包装器,允许用户使用任意约束表达式动态创建优化模型。由于约束表达式是使用符号定义的,
JuMP
要求在当前范围内定义这些符号,因此我希望用户在字典中向函数提供这些符号及其值。全局定义符号会很麻烦,因为理想情况下,用户应该能够使用相同的约束表达式(即相同的符号)但不同的值多次运行函数。

注意:我不是元编程专家

认为您可以这样做,不是使用泛型函数,而是使用宏或生成的函数

基于此:

julia>宏栏(dict)
转储(dict,10)
结束
朱莉娅>@bar Dict(:foo=>“foo”,:bar=>“bar”,:baz=>“baz”);
Expr
头:符号呼叫
args:数组(任意,(4,))
1:符号Dict
2:Expr
头:符号=>
args:数组(任意,(2,))
1:Expr
标题:符号引用
args:数组(任意,(1,))
1:符号foo
典型:有吗
2:ascistring“foo”
典型:有吗
3:Expr
头:符号=>
args:数组(任意,(2,))
1:Expr
标题:符号引用
args:数组(任意,(1,))
1:符号栏
典型:有吗
2:显示“条”
典型:有吗
4:Expr
头:符号=>
args:数组(任意,(2,))
1:Expr
标题:符号引用
args:数组(任意,(1,))
1:符号baz
典型:有吗
2:ascistring“baz”
典型:有吗
典型:有吗
我可以做这样的事情,它可以做更多的错误检查,而且通用宏可以使开发分支中的这项工作更容易(至少对于错误检查而言):

julia>宏foo(dict)
blk=Expr(:块)
如果dict.head==:call&&dict.args[1]==:dict
对于dict.args中的arg[2:结束]
sym=arg.args[1]。args[1]
val=arg.args[2]
推(blk.args,esc(:($sym=$val)))
结束
其他的
错误(“需要Dict{Symbol,Any}”)
结束
黑色
结束
朱莉娅>@foo Dict(:foo=>“foo”,“bar=>“bar”,“baz=>“baz”);
朱莉娅>@show foo bar baz;
foo=“foo”
bar=“bar”
baz=“baz”
julia>让#局部范围
@foo Dict(:foo=>“foo”,:bar=>“bar”,:baz=>“baz”)
@秀福吧
结束;
foo=“foo”
bar=“bar”
baz=“baz”
请注意,您不能创建dict变量,然后将其传递给
@foo
宏(同样可以使这更容易,因为可能还有
Symbol
的方法并发送错误?)

julia>dict=dict(:foo=>“foo”,:bar=>“bar”,:baz=>“baz”);
朱莉娅>@foo dict
错误:类型符号没有字段头
在这一点上,类似于:

for (k, v) in vars
    eval(:($k = $v))
end
@fooa1b2c3

@foo:a=>1:b=>2:c=>3
我觉得这样更好

如果有人向我解释为什么这不是最佳方案,我将不胜感激!这个答案应该是一个注释,但是有很多代码


我将尝试使用通用宏和生成的函数实现类似的功能,并更新帖子。

您应该通过
esc(:($k=$v))
hmm。。。事实上,这是行不通的。是否可以在模块中构建此包装器
eval
将在模块范围内生成变量。您不能通过设计来实现这一点。我相当肯定JuMP有API来实现这一点,而不需要处理本地范围。