# Assignment via iteration over list of variables to be assigned values

Variations on my question have been asked before (How to re-assign values to a List of variables?, How to use Table to assign values to variables in a list?, Assigning values to a list of variable names, Pass the list of variables into function to change their values), but I'm not sure if any of them exactly cover my issue.

((#1 = 1) &) /@ {a, b, c}


sets a, b, and c to 1. However, the similar-looking

Do[x = 1, {x, {a, b, c}}]


does nothing. I assume this is because "Do effectively uses Block to localize values or variables", as stated in the documentation. But once the values have been set, neither approach works to change their values:

((#1 = #1^2) &) /@ {a, b, c}


gives the error message "Set::setraw: Cannot assign to raw object 1.", and

(If[EvenQ[#1], #1 = #1^2] &) /@ {a, b, c}


returns {Null, Null, Null} without changing anything. (The equivalent Do versions don't do anything, as I expected.) Do I need to use Hold or Unevaluated or something to get Mathematica to reassign the variables?

• Dupe? May 10, 2017 at 22:18

Some methods:

Replace[Hold[a, b, c], v_ :> (v = 2), 1] // ReleaseHold;
{a, b, c}

Replace[Hold[a, b, c], v_ :> (v = v^2), 1] // ReleaseHold;
{a, b, c}
(*
{2, 2, 2}
{4, 4, 4}
*)

Function[v, v = 3, HoldAll] /@ Hold[a, b, c] // ReleaseHold;
{a, b, c}

Function[v, v = v^2, HoldAll] /@ Hold[a, b, c] // ReleaseHold;
{a, b, c}
(*
{3, 3, 3}
{9, 9, 9}
*)

SeedRandom;
Do[x /. Hold[v_] :> (v = RandomReal[]), {x, List @@ Hold /@ Hold[a, b, c]}]
{a, b, c}

Do[x /. Hold[v_] :> (v = v^2), {x, List @@ Hold /@ Hold[a, b, c]}]
{a, b, c}
(*
{0.817389, 0.11142, 0.789526}
{0.668126, 0.0124143, 0.623351}
*)


An alternative is to use replacement rules (a List or Association) or Block to insert values when needed. One has to keep the symbols a, b, c, etc. undefined. Here are examples with Association:

Clear[a, b, c]

val = <||>;

(val[#] = 2) & /@ {a, b, c};
{a, b, c} /. val
(*  {2, 2, 2}  *)

(val[#] = #2) &,
{{a, b, c}, -Range@3}];
{a, b, c} /. val
(*  {-1, -2, -3}  *)

Map[
(val[#] = val[#]^2) &,
{a, b, c}];
{a, b, c} /. val
(*  {1, 4, 9}  *)

val
(*  <|a -> 1, b -> 4, c -> 9|>  *)

b^2 - 4 a c /. val
(*  -20  *)