3

I want to loop over a list of variables nad output the variable name and value. E.g., say I have x=1 and y=2, then I want an output

x is 1
y is 2

I suspect I need to use Symbols for this. Here is my approach, but it isn't working:

function t(x,y)
    for i in [x,y]
        println("$(Symbol(i)) is $(eval(i))") # outputs "1 is 1" and "2 is 2"
    end
end

t(1, 2)

Is there a way to achieve this? I guess a Dictionary would work, but would be interested to see if Symbols can also be used here.

TylerD
  • 361
  • 1
  • 9

3 Answers3

6

One option is to use a NamedTuple:

julia> x = 1; y = 2
2

julia> vals = (; x, y)
(x = 1, y = 2)

julia> for (n, v) ∈ pairs(vals)
           println("$n is $v")
       end
x is 1
y is 2

Note the semicolon in (; x, y), which turns the x and y into kwargs so that the whole expression becomes shorthand for (x = x, y = y).

I will also add that your question looks like like you are trying to dynamically work with variable names in global scope, which is generally discouraged and an indication that you probably should be considering a datastructure that holds values alongside labels, such as the dictionary proposed in the other answer or a NamedTuple. You can google around if you want to read more on this, here's a related SO question:

Is it a good idea to dynamically create variables?

Nils Gudat
  • 13,222
  • 3
  • 39
  • 60
4

You can do this by passing the variable names:

x = 1
y = 2

function t(a, b)
    for i in [a, b]
        println("$(i) is $(eval(i))") 
    end
end

t(:x, :y)
x is 1
y is 2

At the start of the function, there's no record of the "x"-ness of x, or the "y"-ness of y. The function only sees 1 and 2. It's a bit confusing that you also called your two local variables x and y, I renamed them to show what's happening more clearly.

A solution with dictionaries would be nicer:

dict  = Dict()

dict[:x] = 1
dict[:y] = 2

function t(d)
    for k in keys(d)
        println("$(k) is $(d[k])") 
    end
end

t(dict)
y is 2
x is 1
daycaster
  • 2,655
  • 2
  • 15
  • 18
3

If you rather want to see programmatically what variables are present you could use varinfo or names:

julia> x=5; y=7;

julia> varinfo()
  name                    size summary
  –––––––––––––––– ––––––––––– –––––––
  Base                         Module
  Core                         Module
  InteractiveUtils 316.128 KiB Module
  Main                         Module
  ans                  8 bytes Int64
  x                    8 bytes Int64
  y                    8 bytes Int64

julia> names(Main)
7-element Vector{Symbol}:
 :Base
 :Core
 :InteractiveUtils
 :Main
 :ans
 :x

With any given name it's value can be obtained via getfield:

julia> getfield(Main, :x)
5

If you are rather inside a function than use @locals macro:

julia> function f(a)
         b=5
         c=8
         @show Base.@locals
       end;

julia> f(1)
#= REPL[13]:4 =# Base.@locals() = Dict{Symbol, Any}(:a => 1, :b => 5, :c => 8)
Dict{Symbol, Any} with 3 entries:
  :a => 1
  :b => 5
  :c => 8
Przemyslaw Szufel
  • 40,002
  • 3
  • 32
  • 62