# Mathematica Documentation for HoldAll: Unevaluated doesn't do anything?

I'm trying to understand the difference between HoldAll and Unevaluated. The documentation for HoldAll, under "Application", lists the following example:

(* Use HoldAll and Unevaluated to suppress evaluation of symbols wherever it would occur: *)

In[1]:= SetAttributes[symbolLength, HoldAll];
symbolLength[s_Symbol] := StringLength[SymbolName[Unevaluated[s]]]

(* Find the length of a symbol's name even if it has a value: *)

In[2]:= xyzzy = 1;

In[3]:= symbolLength[xyzzy]

Out[3]= 5


The problem is that if you define symbolLength without Unevaluated, i.e.

symbolLength[s_Symbol] := StringLength[SymbolName[s]]


then the function still returns 5. So what's the point of Unevaluated? Also, more generally, shouldn't HoldAll already keep s unevaluated? And if that's the case, then is there any reason to combine HoldAll and Unevaluated in the same function?

• I get an error, not 5, in the second version: i.sstatic.net/U6zUR.png Commented Jul 18, 2021 at 4:45

The difference is in what happens if the symbol you are passing in has a value assigned.

SetAttributes[symbolLength1, HoldAll];
symbolLength1[s_Symbol] := StringLength[SymbolName[s]]

SetAttributes[symbolLength2, HoldAll];
symbolLength2[s_Symbol] := StringLength[SymbolName[Unevaluated[s]]]

asd = 1

In[15]:= symbolLength1[asd]

During evaluation of In[15]:= SymbolName::sym: Argument 1 at position 1 is expected to be a symbol.

During evaluation of In[15]:= StringLength::string: String expected at position 1 in StringLength[SymbolName[1]].

Out[15]= StringLength[SymbolName[1]]

In[16]:= symbolLength2[asd]

Out[16]= 3


The role of the HoldAll attribute is to ensure that when evaluating symbolLength2[asd], then asd does not evaluate before symbolLength2[...] does.

The role of Unevaluated is to ensure that the evaluation sequence inside of symbolLength2 will be this:

SymbolName[Unevaluated[asd]] -> SymbolName[asd] -> "asd"

And not this:

SymbolName[asd] -> SymbolName[1] -> error

HoldAll has no impact on what happens to asd once it has been substituted into the right-hand-side of symbolLength2's definition. It merely makes it possible to make this substitution without evaluating asd first. After this initial substitution, evaluation control is in your hands.

The best tutorial on understanding evaluation control is "Working with Unevaluated Expressions" by Robby Villegas: https://library.wolfram.com/infocenter/Conferences/377/

You may also want to go through the Evaluation of Expressions documentation page, which describes how Unevaluated is treated in a non-standard way.

https://reference.wolfram.com/language/tutorial/EvaluationOfExpressions.html