4
$\begingroup$

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?

$\endgroup$
5
$\begingroup$

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[1];
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}  *)

MapThread[
  (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  *)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.