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.
No it’s not possible and you shouldn’t do it. Use a Dict
instead.
You might want to look into metaprogramming.
http://docs.julialang.org/en/release-0.5/manual/metaprogramming/
or use a Dict
as @yuyichao suggests.
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
If you only care about global variables then something similar to this will certainly work.
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.
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.
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.
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.
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
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
.
Why? In what contexts do you need this quite often?
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.
There’s nothing in that problem that requires using string as variable names. You need string to access objects, variable names never comes in.
Use a Vector
?
name[1]
, name[2]
etc.
EDIT: Or a Dict