1
$\begingroup$

I often find it useful to define a symbol from strings (often in a loop in which I define other symbols). This I accomplish with Symbol (and often ToString).

However, if the symbol has already been defined, my call to Symbol returns not the symbol, but that to which the symbol evaluates.

This may arise rarely, but I stumbled upon it when automatically generating usage messages, as in the following example.

vars = {x,y};
x$dN = {x1, x2};
y$dN = {y1, y2};
For[ i = 1, i <= Length[vars], i++,
  Evaluate[
    Symbol[
      ToString[vars[[i]]] <> "$dN"
    ]
  ]::usage
  =
  "generic (no argument) thermodynamic quantity vector"
]

(* Symbol::symname: The string "{x1, x2}$dN" cannot be used for a symbol name. 
   A symbol name must start with a letter followed by letters and numbers" *)

This is the obvious error because I'm trying to define the usage for x$dN, which evaluates to x$dN = {x1, x2}.

So my question is: can we sometimes leave a symbol unevaluated, yet use it as a symbol?

$\endgroup$
3
  • 1
    $\begingroup$ Try something like ReleaseHold@Hold[MessageName][ToExpression["symb", InputForm, Hold], "usage"]. Using ToExpression with a third argument is key here. $\endgroup$ May 12, 2014 at 19:41
  • $\begingroup$ @JacobAkkerboom, your solution was easiest for me to instantiate. Thanks! $\endgroup$ May 12, 2014 at 20:00
  • 1
    $\begingroup$ Fundamentally this has been covered a number of times before. Despite this not being an exact duplicate it surely "already has an answer" there: (197), (783), (2651), (2926), (37755) Therefore I shall close it to prevent redundant efforts. $\endgroup$
    – Mr.Wizard
    May 12, 2014 at 22:29

1 Answer 1

6
$\begingroup$

In your example it is possible to assign a usage message although the variable has a value. Short example:

var = 1;
Function[v, v::usage = "blue", HoldFirst] @@ MakeExpression["var"]

The trick is to keep the variable var unevaluated all the time which can be tricky.

In my example above this is accomplished by three things:

  • MakeExpression does what Symbol does in your code, but it wraps the result automatically in HoldComplete. Therefore, var will not be evaluated at this point
  • Function[....,HoldFirst] creates a functions which too, holds its first argument unevaluated.
  • MessageName which is the symbol::msg operator too holds its first argument. Check Attributes[MessageName] to see that.
$\endgroup$
1
  • $\begingroup$ halirutan, thanks for the thorough explanation! $\endgroup$ May 12, 2014 at 20:01

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