Best way to create/assign variables based on strings


Hi all

Which would be best way to create/assign variables based on strings. Assuming I have this:

string = “AA”
string = get(“https://get.some.unknown.very.short.string”)

would like to do the following

AA = 1
new_variable_named_on_that_yet_unknown_short_string = 1

Thank you!


Sorry not answering your question, but consider using JSON.jl.


Use a dictionary:


If this is in global scope. Use eval. If this is local scope, it’s impossible and won’t be possible. Use a Dict with String as keys to hold the value instead.


Here is the code, but this is not the best practice:

julia> string = "AA"

julia> value = 1

julia> eval(parse("$string=$value"))

julia> AA



Even if you want to use eval. DO NOT USE parse.

Do @eval $(Symbol(string)) = $value or @eval $(Symbol(string)) = value.


Thank you for all the answers.

[quote=“yuyichao, post:4, topic:3001, full:true”]
If this is in global scope. Use eval. If this is local scope, it’s impossible and won’t be possible. Use a Dict with String as keys to hold the value instead.
Found a “solution” in local scope by widening the field of permissible functions. In my setting “AA” and “BB” represent those short-strings yet to be fetched
var1 = "AA"
var2 = "BB"

but on the contrary, x and y are known at coding time

x = 2.0
y = rand(2,2)

An ugly solution may be:

function crazymeta(file)
open(file, "w") do f
write(f,"$var1 = x\n$var2 = y")
return AA * BB

CC = crazymeta("whatever.jl")

Now AA = 2.0, BB and CC are naturally 2x2 Array{Float64,2}. Would it possible to do something like this print/include trick, but with all steps in memory and reasonably fast?


Well you could use include_string, but include operates at global scope.
In your example, AA and BB will be defined as global variables.
In this case, probably best to go with @yuyichao’s suggestion and use @eval.


A better way to write this is

var1 = "AA"
var2 = "BB"
@eval $(Symbol(var1)) = x
@eval $(Symbol(var2)) = x
CC = AA * BB

but again, this is not usually the best way to go about things. What are you trying to do? By that I mean your actual goal, for which this metaprogramming may likely not be the best solution for.


I agree that using a Dict is better in most cases. However, by defining a macro it is certainly not impossible to create variables in local scope only. I posted one possible solution in another thread. Or did I misunderstand what you meant?


No it’s impossible to create a variable in local scope from runtime value. You can of course use a macro to translate @m "b" into b = 1 but it’s impossible to make var = "b"; @m var behave like b = 1.


In another word, if there’s a way to do this (create local variable from runtime value), it’s a semantic bug that needs to be fixed.


I see. I should have read the original post more carefullly instead of jumping all over my example in the other thread. Thanks for clarifying!


Note that the macro is very unlikely the right solution in the other thread either. It essentially let you spell variable syntax slight differently, like writing "a" = 1 instead of a = 1, which might be cool if you really like quoting but I don’t think that’s what the OP asked about in either thread.


Sorry for nagging, but there is obviously something I still don’t understand. The macro in the other thread seems to work (the function creates a random runtime value and the macro creates a variable with that value in the local scope). Here’s the code:

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

function newtest()
    c = rand()  
    @localvariable("b", c)
    println("b in function = $b")

isdefined(:b) && println("global b = $b")


b in function = 0.8428874752942634

What am I missing?


What you are missing is that the macro isn’t useful other than making it possible to do things like

It does NOT create a variable whose name is determined at runtime, merely changing how you spell assignments. Also, it’s missing esc.


I have a use case for which I could probably use strings as variable names. I want to construct a graph with some vertices. Since I want to create them iteratively, I use a for loop here but this doesn’t work as expected.

for i = 1:max_nodes
  @eval $(Symbol("V$i")) = ExVertex(i, "V$i")

So, I switched back to your primary suggestion of using Dictionaries. So far, they work fine.

vertices = Dict("V$i" => ExVertex(i, "V$i") for i=1:max_nodes)