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.
Answer
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.
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:
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}
Comments
Post a Comment