使用元编程在Julia中声明顶层变量

8

我希望能够利用元编程回答这个问题,但是for循环的作用域规则导致我的变量不能在最上层(REPL)的作用域中被定义:

for x = [:A1, :A2]
   @eval x = rand(2,2)
end

我知道可能有一种简单的方法来解决这个问题,但是我的周五晚上的大脑想不出来。你们其中有没有元编程专家能帮我找到一个简洁的解决方案呢?(我知道宏可能会在转义时起作用,但我正在尝试想出更短的东西)


我也看到了,不禁想知道如果你有一百个A,你将如何进行元编程。 for x=1:100 然后呢?变量名如何可以通过编程方式生成? - rickhg12hs
1
回答了自己的评论/问题。for k=1:10 my_sym = symbol("A"*string(k)); @eval $my_sym = rand(2,2) end(此处显示生成A1到A10。) - rickhg12hs
1个回答

11

如果您只想在全局作用域中定义变量,那么您只是忘了加一个$

for x = [:A1, :A2]
    @eval $x = rand(2,2)
end

但是@eval始终在顶层评估,即使将其放置在函数内部。如果您想在函数作用域中定义变量,则需要将整个函数放入@eval中,构造代码块,并将其插值到函数中:

@eval function f()
    ...
    $([:($x = rand(2, 2)) for x in [:A1, :A2]]...)
    ...
end

这段代码可以很容易地改写成宏形式(但是这时需要使用 esc)。


啊,谢谢。对于你的第二个例子,我尝试了一个简化版本,但是出现了错误:julia> @eval $([:($x = rand(2,2)) for x in [:B1,:B2]]...) ERROR: type: apply_type: 在Vararg中,期望Type{T<:Top},得到Array{Expr,1} - JKnight
1
似乎你需要使用 @eval begin $([:($x = rand(2,2)) for x in [:B1,:B2]]...) end 或者 eval(Expr(:block, [:($x = rand(2,2)) for x in [:B1,:B2]]...)) 才能实现。但我不确定这样做有什么意义,因为即使将其放在函数内部,它仍会在全局范围内定义变量。如果这正是你想要的,那么我认为我的第一个示例看起来更好一些。 - simonster

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接