4

This is probably a really simple one, but I'm stumped. I want Symbol["x"]=3 to work just like x=3. However I can't figure out how to get Mathematica to evaluate the Symbol, converting the string to the symbol x, but then not evaluate x.

x = 2

2

Symbol["x"] = 3

Set::write: Tag Symbol in Symbol[x] is Protected. >>

3

Evaluate[Symbol["x"]] = 2

Set::setraw: Cannot assign to raw object 3. >>

2

I know that I can remove the definition, but I have a ton of these and would like to be able to replace their values that have been already set. x=3 doesn't require that I remove the definition of x to set it.

In case it matters, I'm using 10.0.0.

Mark Adler
  • 4,949
  • 1
  • 22
  • 37
  • This fundamental question has been asked and answered repeatedly: (197) (783) (2651) (2926) (37755). Please review those and pick the one that you feel is closest, and I will close this accordingly. Examples of solutions: Set @@ Append[ToHeldExpression["x"], 3] or MakeExpression@"x" /. _[s_] :> (s = 4) – Mr.Wizard Aug 28 '14 at 16:53
  • And: ToExpression["x", StandardForm, Function[s, s = 5, HoldFirst]] – Mr.Wizard Aug 28 '14 at 17:02
  • @Mr.Wizard I think I found a possible new solution: Clear[x]; Activate[Inactive[Set][Symbol["x"],3]] I agree we can close this question, as a duplicate of How do you programatically load data into symbols?. Then I'll post my answer there. – Jens Aug 28 '14 at 17:48
  • Thanks! When I searched I didn't find any of those. The closest is 783. – Mark Adler Aug 28 '14 at 17:57
  • Yes, ToExpression looks like the right approach. ToHeldExpression is marked as obsolete. – Mark Adler Aug 28 '14 at 17:58
  • @MarkAdler Even though I voted to close it, I upvoted your question because it made me think... – Jens Aug 28 '14 at 17:59
  • @Jens: Clear[x] is not useful, since I would actually have to do Clear[Symbol["x"]], which runs into exactly the same problem. – Mark Adler Aug 28 '14 at 18:00
  • 2
    While ToExpression works, I was hoping for something that gave finer control over evaluation, e.g. allowing only one step of the evaluation to take place. Control of evaluation has always been a bugaboo for me in using Mathematica. – Mark Adler Aug 28 '14 at 18:04
  • So what I did may be a Bad Thing, but it is this: Unprotect[Set]; Set[s_?StringQ, v_] := ToExpression[s, StandardForm, Function[x, x = v, HoldFirst]]; Protect[Set];. Then I can simply "x"=3 and it works! Set normally gives an error if the left hand side is a string, so I think this is ok. For me anyway, this is a natural and useful extension of Set. – Mark Adler Aug 28 '14 at 18:15
  • "Bad Thing" may be putting it mildly. Anyway, in my answer (comment) I used Clear only to get a clean slate for my answer to your question, thinking that you were asking only about Set here. – Jens Aug 28 '14 at 18:17
  • Ah. I hadn't tried it. So the Clear is not necessary? The whole point of the question is to not have to clear the definition of x first. If you clear the definition first, then the Evaluate works fine, since the symbol x evaluated is just x. – Mark Adler Aug 28 '14 at 18:18
  • @Mark regarding "Clear is not useful"` that is not true; see: (37755) – Mr.Wizard Aug 28 '14 at 18:19
  • Ah, ok. I didn't know that Clear works on strings. In any case, I want to be able to do this without clearing the definitions, and your ToExpression approach does the trick. – Mark Adler Aug 28 '14 at 18:20
  • 1
    @Mark Rather than modifying Set I recommend that you use an UpSet on a special head as WReach did here and I did here. Proposal: Set[svar[s_?StringQ], R_] ^:= MakeExpression@s /. _[L_] :> (L = R) now svar["x"] = 5 works. You should probably then Protect[svar] to prevent unwanted assignments. – Mr.Wizard Aug 28 '14 at 18:27
  • @MarkAdler Thanks for clarifying the importance of Clearing variables in your question. Looks like @Mr.Wizard has the thing you need... – Jens Aug 28 '14 at 18:28
  • @Mark It occurs to me that for programmatic applications your _?StringQ is probably necessary as you may not have a literal string but rather an expression that evaluates to a string. I changed my code above to reflect this. – Mr.Wizard Aug 28 '14 at 18:34

0 Answers0