# Assigning values to a list of variable names

As part of a calculation I need to do something like this

Evaluate[{aaa, bbb, ccc}[[ index]]] = {1, 2, 3, 4, 5}


so if index is 1 then {1, 2, 3, 4, 5} will be stored into the variable aaa.
But if I re-evaluate this it does not work because aaa is now a list and not a variable. I tried various options with Hold[] etc but did not manage to solve this.

• Related: (1), (2), (3), (4), (5) Jun 6, 2012 at 23:49
• All: please comment if you believe this question or any of the "Related" ones should be merged. Jun 6, 2012 at 23:54
• By the way please also see: Elegant manipulation of the variables list Aug 27, 2014 at 6:52

This is a fairly natural question and I feel it is worthy of attention. I am going to answer in two parts. First, I am going to show a method that is more appropriate for Mathematica programming and which I recommend you use instead. Then I will show how to force the action you are attempting.

# Better Alternatives

The common way to accomplish programmatically selected assignments is to use indexed variables. This allows you to assemble a "variable" from inert parts. For example, one would use a single variable var and simply make assignments (SeedRandom[1] for a consistent result):

SeedRandom[1]

Do[
var[i] = RandomInteger[9],
{i, {1, 2, 3, 2, 3, 1, 3}}
]


Or recall them:

var /@ {1, 2, 3}

{0, 7, 8}


If you desire a certain name be attached to a value you can index with Strings.

names = {"aaa", "bbb", "ccc"};

i = 1;

var[ names[[i]] ] = Sqrt[2]; (* dummy first assignment *)

var[ names[[i]] ] = {1, 2, 3, 4, 5};

var["aaa"]

{1, 2, 3, 4, 5}


In passing, depending on your application you may find Rules applicable.

### Associations

Mathematica 10 introduced Associations which are like self-contained "indexed variables." Use is similar but you need to start with an (optionally empty) Association before you make assignments. Example:

SeedRandom[1]

asc = <||>;

Do[asc[i] = RandomInteger[9], {i, {1, 2, 3, 2, 3, 1, 3}}]

asc

<|1 -> 0, 2 -> 7, 3 -> 8|>


Values may be recalled using Map, Replace, or Lookup; for a comparison see:

For some ideas of when and why one might use associations over "indexed variables" see:

# Forcing the behavior

Suppose you need the behavior you asked for to keep a large program working without extensive modification.

### Method #1

This works because Part preserves the head of the expression, here Unevaluated.

Ignore the syntax highlighting in Unevaluated: this is a nonstandard but safe use.

This could easily use the same syntax as Method #2: assign[symbols_, idx_, val_] :=

ClearAll[aaa, bbb, ccc, assign]
assign[idx_, val_] := (# = val) & @ symbols[[1, {idx}]]

symbols = Hold @ Unevaluated[aaa, bbb, ccc];

assign[1, "dummy"];
assign[1, Range@5];

aaa

{1, 2, 3, 4, 5}


### Method #2

This uses the injector pattern in preference to Unevaluated.

ClearAll[aaa, bbb, ccc, f1, assign]
assign[symbols_, idx_, val_] := symbols[[{idx}]] /. _[x_] :> (x = val)

symbols = Hold[aaa, bbb, ccc];

assign[symbols, 1, "dummy"];
assign[symbols, 1, Range@5];

aaa

{1, 2, 3, 4, 5}

• Cool! For Association Lists I would add ClearAll[assign]; SetAttributes[assign, HoldFirst]; assign[association_, key_, val_] := Hold[association[key]] /. _[x_] :> (x = val) Jul 19, 2017 at 19:24
• @tchronis You should not need the injector pattern here; a straightforward assignment will work: SetAttributes[assign, HoldFirst]; assign[association_, key_, val_] := association[key] = val. Much of the time I would just write out (asc[#] = #2) & however if I needed to apply that across a set of keys and values. Jul 20, 2017 at 6:39
• you are right. I overcomplicated things here. When the keys are themselves global variables it can be confusing (that was my case). Thank you. Jul 20, 2017 at 7:35

Keep data out of your variable names

Use functional programming where, whenever you use aaa, it is an argument to a function. If you want to pass something different in, call the function.

If you really want to do this, use one of the HoldAll-like attributes here.

I would not recommend it, but you could do something like

varlist = "var1,var2,var3";
index   = 2;
ToExpression[StringSplit[varlist, ","][[index]] ~~ "={1, 2, 3, 4, 5}"];
var2
(* -> {1, 2, 3, 4, 5} *)