# Assign value to the symbol returned by function

Ok, so here is example code:

Clear[p, flag, k];
p = 2;
k = 1;
flag = True;
If[flag, p, k] = 0;
p


After that I get the message

Set::write: Tag If in If[True,p,k] is Protected.


And p is still 2 instead of 0. How can I make the p equal to 0 in this case?

EDIT: My question is general - how to return the symbol from some function, not only If - and be able to change its value later (for example by Set)

EDIT #2: I know that with associations I can do that easily:

Clear[p, flag, k];
v = <||>;
v[p] = 2;
v[k] = 1;
flag = True;
v[If[flag, p, k]] = 0;
v[p]


I just wish I could the same just on symbols..

• Your are trying to define a value for the function "If", but "If" is protected. "If" can not be on the left side of an assignment.. Even if it were executed, you would then have "2=0". Sep 23, 2020 at 16:23
• I know but how to assign to p properly then ? Sep 23, 2020 at 16:24
• Or in general, how to return from that if the symbol and then assign value to it? Sep 23, 2020 at 16:26
• It is not exactly clear what you want to do. Perhaps: If[flag,p=0,k=0] Sep 23, 2020 at 16:28
• So i have to write = 0 twice? There is no option to get just the symbol and then assign? Sep 23, 2020 at 16:31

At first I wasn’t sure how to realize this, but upon seeing m_goldberg’s example with Set inside of If, it hit me:

Clear[p, flag, k];
p = 2;
k = 1;
flag = True;
If[flag, Set[p,#], Set[k,#]]&;
p


And this, of course, returns 0 if flag = True and 2 if flag = False.

It might be easier to see it this way:

Clear[p, flag, k];
p = 2;
k = 1;
flag = True;
If[flag, p=#, k=#]&;
p


which also works like the above. You could streamline this a bit more & wrap it into a function, but I think this answers your question & gives it to you in a form that is loose enough for you to modify to your desires! Nothing fancy, just anonymous functions.

• +1 I also had your 2nd example as an afterthought, but when I signed in to update my answer, i was way too late. Sep 24, 2020 at 9:56
• @m_goldberg you could update/expand upon the 1st example you have by having ”=“<>ToString[arg] and make it a function, where arg is 0, for OP’s case? Maybe that’s a bit less concise though... Sep 24, 2020 at 11:47

Here are two methods that are essentially the same.

Clear[p, flag, k];
p = 2;
k = 1;
flag = True;
Evaluate[If[flag, p =.; p, k =.; k]] = 0;
p  {* 0 *}


If you want to use a function, maybe this method:

Clear[func, p, flag, k];

func[flag_?BooleanQ, str1_String, str2_String] := If[flag,
Clear[str1]; ToExpression[str1],
Clear[str2]; ToExpression[str2]]

p = 2;
k = 1;
flag = True;
Evaluate[func[flag, "p", "k"]] = 0;
p  (* 0 *)


The salient points are (1) the symbol must be cleared or unset and (2) use Evaluate on the left side of the equals sign.

Here is a fairly concise but still silly way to do it.

Clear[p, flag, k];
p = 2;
k = 1;
flag = True;
ToExpression[If[flag, "p", "k"] <> "=0"];
p

0


However, I would rather write

Clear[p, flag, k];
p = 2;
k = 1;
flag = True;
If[flag, p = 0, k = 0];
p


and, I believe, so would everybody else. it is the standard practice and is both more concise and efficient then any playing games to limit the code to one written Set expression.