Unevaluated¶
Status: Stable
documented, exercised by the test suite and/or worked examples, with no known limitations recorded.
Description¶
Unevaluated[expr]
represents the unevaluated form of expr when it appears as the argument to a function.
Notes
f\[Unevaluated\[expr\]\] effectively works by temporarily holding that argument, then evaluating f\[expr\] with the wrapper removed. The wrapper is NOT removed when the argument is held (e.g. when f has HoldAll, HoldFirst, or HoldRest applies) or when f has attribute HoldAllComplete. Sequence expressions directly inside Unevaluated are NOT flattened: Length\[Unevaluated\[Sequence\[a, b\]\]\] gives 2. Unevaluated has attributes {HoldAllComplete, Protected}, so its own argument is itself protected from evaluation, Sequence flattening, and wrapper stripping.Examples (12)¶
Every input below was run against the current Mathilda build and its output recorded.
Basic examples (6)¶
In[1]:= Length[Unevaluated[Plus[5, 6, 7, 8]]]
Out[1]= 4
In[2]:= Length[Unevaluated[Sequence[a, b]]]
Out[2]= 2
In[3]:= Hold[Unevaluated[1+2]]
Out[3]= Hold[Unevaluated[1 + 2]]
In[4]:= SetAttributes[f, HoldAll]; f[Unevaluated[1+2]]
Out[4]= f[Unevaluated[1 + 2]]
In[5]:= HoldComplete[Unevaluated[1+2]]
Out[5]= HoldComplete[Unevaluated[1 + 2]]
In[6]:= Attributes[Unevaluated]
Out[6]= {HoldAllComplete, Protected}
Applications (6)¶
Length sees the held Plus, not a sum
Stripping happens after Sequence splicing
A genuinely held slot keeps the wrapper
In[11]:= HoldComplete[Unevaluated[1 + 2]]
Out[11]= HoldComplete[Unevaluated[1 + 2]]
In[12]:= Attributes[Unevaluated]
Out[12]= {HoldAllComplete, Protected}
Implementation notes¶
Unevaluated has no C handler; the attribute table (src/attr.c) gives it ATTR_HOLDALLCOMPLETE | ATTR_PROTECTED. The evaluator (src/eval.c) special-cases it: in a non-held argument position f[Unevaluated[expr]] passes expr itself (unevaluated) to f, stripping the wrapper. In held positions and under HoldAllComplete heads the wrapper is preserved.
- Attributes:
{HoldAllComplete, Protected}. f[Unevaluated[expr]]passesexprtofas ifftemporarily held that single argument; theUnevaluatedwrapper is then stripped beforef's body runs, effectively yieldingf[expr]withexprunevaluated.- The wrapper is stripped only in positions that would otherwise be evaluated (non-held slots). Its purpose is to make an ordinary head hold an argument it would normally evaluate; stripping removes the wrapper but does not force evaluation of the exposed content for that one step, so
Length[Unevaluated[1+2+3]]gives3(Length sees the heldPlus[1,2,3], not6). - The wrapper is not stripped in a genuinely held slot — when
fhasHoldAll, orHoldFirst/HoldRestapplies to that position — because the argument was never going to be evaluated:Hold[Unevaluated[1+2]]givesHold[Unevaluated[1+2]], and withHoldAllf,f[Unevaluated[1+2]]givesf[Unevaluated[1+2]]. - The wrapper is likewise not stripped when the enclosing function has
HoldAllComplete(e.g.HoldComplete, orUnevaluateditself). - Stripping happens after
Sequenceflattening, so aSequencedirectly insideUnevaluatedsurvives into the argument slot (Length[Unevaluated[Sequence[a, b]]]gives2). - Nested
Unevaluatedwrappers are stripped one layer per evaluation step. - As a top-level expression,
Unevaluated[expr]evaluates to itself (because ofHoldAllComplete).
Attributes: HoldAllComplete, Protected.
References¶
See also: HoldAll, HoldFirst, HoldRest, HoldAllComplete, HoldComplete, Sequence
- Source:
src/eval.c - Specification:
docs/spec/builtins/expression-information.md - Tests:
tests/test_evaluate.c - Tests:
tests/test_expr_pool.c - Tests:
tests/test_graph.c - Tests:
tests/test_purefunc.c
Notes & additional examples¶
Notes¶
f[Unevaluated[expr]] makes an ordinary head f hold the single argument expr
that it would normally evaluate: the wrapper is stripped in the non-held slot, but
stripping it does not force evaluation of the exposed content for that step —
so Length[Unevaluated[1 + 2 + 3]] is 3, because Length sees the held
Plus[1, 2, 3].
The wrapper is not stripped in a slot that was already held — under HoldAll,
HoldFirst/HoldRest, or HoldAllComplete — because the argument was never going
to be evaluated: Hold[Unevaluated[1 + 2]] stays intact. Stripping happens after
Sequence flattening, so a Sequence directly inside Unevaluated survives into
the argument slot. Unevaluated itself carries HoldAllComplete, so as a
top-level expression it evaluates to itself.