8

I want to answer this question using metaprogramming, but the scoping rules of for loops are causing my variables to not be defined in the upper-most (REPL) scope:

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

I know there's probably an easy way around this, but my Friday night brain can't think of one. Can one of you metaprogramming junkies help me find a succinct solution? (I realize a macro might work with escaping, but I'm trying to think of something shorter)

JKnight
  • 1,996
  • 2
  • 14
  • 23
  • I saw that too and wondered how you would metaprogram it if you had a hundred A's. `for x=1:100` and then what? How can variable names be made programmatically? – rickhg12hs Sep 27 '14 at 07:36
  • 1
    Answered my own comment/question. `for k=1:10 my_sym = symbol("A"*string(k)); @eval $my_sym = rand(2,2) end` (Shown here generating A1 through A10.) – rickhg12hs Sep 27 '14 at 08:21

1 Answers1

11

If you only want to define the variables in the global scope, you're just missing a $:

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

But @eval is always evaluated at top level even if you put it inside a function. If you want to define the variables in a function scope, you need to put the entire function inside @eval, construct the code block, and interpolate it into the function:

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

This code can also be trivially adapted into a macro (but then it does need esc).

simonster
  • 556
  • 3
  • 8
  • Ahh, thanks. for your second example I tried a cut down version but got: julia> @eval $([:($x = rand(2,2)) for x in [:B1,:B2]]...) ERROR: type: apply_type: in Vararg, expected Type{T<:Top}, got Array{Expr,1} – JKnight Sep 27 '14 at 15:15
  • 1
    Seems you need `@eval begin $([:($x = rand(2,2)) for x in [:B1,:B2]]...) end` or `eval(Expr(:block, [:($x = rand(2,2)) for x in [:B1,:B2]]...))` for that to work. But I'm not sure there's much point, since that will still define the variables at global scope even if you put it inside a function, and if that's what your after I think my first example looks a bit nicer. – simonster Oct 02 '14 at 23:42