String as a variable name

How can I convert a string to variable name an assign some value to this variable? In R I use assign() function for this, but I was not able to find its equivalent in Julia.

2 Likes

No it’s not possible and you shouldn’t do it. Use a Dict instead.

8 Likes

You might want to look into metaprogramming.

http://docs.julialang.org/en/release-0.5/manual/metaprogramming/

or use a Dict as @yuyichao suggests.

1 Like

OR you can use simple function (metaprogramming):

## string to varname function, see
## https://groups.google.com/forum/#!topic/julia-dev/z-dyQ_jUgk8
function string_as_varname(s::AbstractString,v::Any)
         s=symbol(s)
         @eval (($s) = ($v))
end
5 Likes

If you only care about global variables then something similar to this will certainly work.

2 Likes

As @yuyichao pointed towards, eval works in the global scope, so this may not work the way you think it would inside of a function.

2 Likes

Doing it as a macro seems to work correctly inside a function (i.e. variables are created only in the local scope):

macro string_as_varname_macro(s::AbstractString, v::Any)
	s = Symbol(s)
	esc(:($s = $v))
end

function string_as_varname_function(s::AbstractString, v::Any)
	s = Symbol(s)
	@eval (($s) = ($v))
end

function test()
	string_as_varname_function("a",2)
	@string_as_varname_macro("b",3)
	println("(a,b) = ($a,$b)")
end

test()
isdefined(:a) && println("a = $a")
isdefined(:b) && println("b = $b")
nothing

Output:

(a,b) = (2,3)
a = 2

I’ve only been working with Julia for a few weeks, so please explain if this has some unintended side effect.

3 Likes

As @yuyichao suggested, you are almost certainly going about the wrong way to do something. If you explain a little more about what you are trying to do, we could probably suggest something better.

2 Likes

I don’t know why Aaron1488 wants to do this, but I have a use case.

When building large optimization models in JuMP, you will often want to assign values to model parameters using external files in spreadsheets. When your model contains complex equations, it really helps readibility and maintainability if you can write parameter1D and parameter3D[a,b,c] in your equations instead of looking up parameters in a Dict like allparameters["parameter1D"] and allparameters["parameter3D",a,b,c].

I guess you could first read the external data into the Dict and then manually add local variable aliases for each parameter, but that gets verbose and messy when you have dozens of parameters.

I think using the macro to define local variables for parameters is the best solution, but I’m open to suggestions if someone has a better idea.

Perhaps the @unpack macro in https://github.com/mauro3/Parameters.jl can be useful.

1 Like

You can also use the @with macro in DataFramesMeta

using DataFramesMeta

a = Dict(:parameter1D => [1,2,3])
@with a begin
   :parameter1D.^2
end

I’m doing a similar exercise and wondered what solution you opted for i.e. did you just accept cumbersome dictionary format or go for something else? I’m probably going to do what you mention here: “I guess you could first read the external data into the Dict and then manually add local variable aliases for each parameter” unless anyone has any good suggestions.

In Julia 1.0, you can now use getproperty overloading to make accessing the dictionary more concise:

julia> struct Params
         data::Dict{String, Any}
       end

julia> Base.getproperty(p::Params, name::Symbol) = getfield(p, :data)[String(name)]

julia> p = Params(Dict("foo" => 1, "bar" => [1,2,3]))
Params(Dict{String,Any}("bar"=>[1, 2, 3],"foo"=>1))

julia> p.foo
1

julia> p.bar
3-element Array{Int64,1}:
 1
 2
 3
8 Likes

But quite often you need to generate variable names programatically such as name1, name2, name3… How can you get it with Dicts?

In local scope? For global scope you could use eval.

1 Like

Why? In what contexts do you need this quite often?

1 Like

The only context I can think of where you do need to “generate variable names programatically” is when you are generating code programatically (which is basically repeating myself since variable names is part of code). And yes, in those cases, as long as you can obtain the compile time information you want you can do whatever you want to genenrate the code.

When you need a fast albeit inelegant way to sort through individually meaningless parts of large data-set, as is often the case in scientific programming.

1 Like

There’s nothing in that problem that requires using string as variable names. You need string to access objects, variable names never comes in.

4 Likes

Use a Vector?
name[1], name[2] etc.

EDIT: Or a Dict

1 Like