SymbolName applied to a list of variables, some of which may have values assigned

164 Views Asked by At

In Mathematica:

I would like to pass a variable number of arguments to a function.

I would like to print the name of each argument. The problem is that SymbolName evaluates its input. For a given variable, you can get around this:

a=18;
SymbolName[Unevaluated[a]]

works. But that won't work if the variable is in a list. For example:

printname[x__]:=Print[Table[SymbolName[Unevaluated[{x}[[i]]]],{i,1,Length[{x}]}]];
printname[a,b,c]

will not work. Any suggestions?

Thanks in advance.

1

There are 1 best solutions below

1
On

Mathematica tries to evaluate the argument of Unevaluated[] when you call it. So {x}[[i]] gets converted into {18, b, c}[[i]] which you didn't want and then the iteration over i doesn't work anymore because Unevaluated[] doesn't let the Table access the iterator.

So, to really solve the issue you should disable Mathematica's evaluation completely for the functions that you want to pass the symbols through.

In[1]:= SetAttributes[SymbolName, HoldAll];
        SetAttributes[Map, HoldAll];

After this you can just do

In[2]:= a=18; SymbolName @@@ Unevaluated /@ {a, b, c}
Out[2]:= {a, b, c}

where @@@ and /@ are shorthand for Apply[] and Map[].

Setting Hold[] or similar attributes in Mathematica's built in functions can lead to trouble. See this question and answer in the Mathematica stackexchange for more information.

Specifically, to make a function that takes an arbitrary number of arguments would be

sym = SymbolName @@@ Unevaluated /@ {##} &

But the List[] function that takes the sequence of arguments ## for the function & will again evaluate a and turning HoldAll on for List[] is not OK.

Thus the easiest way to do this is to define a function with HoldAll that just passes the args into a Block[] as the list of local variables. This makes a creates an isolated context where the variables do not evaluate to anything.

In[1]:= SetAttributes[f, HoldFirst];
In[2]:= f[seq__] := Block[{seq}, Print[SymbolName /@ {seq}]];
In[3]:= a=18; f[a, b, c]
Out[3]:= {a, b, c}