Skip to content

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

In[7]:= Length[Unevaluated[Plus[5, 6, 7, 8]]]
Out[7]= 4
In[8]:= Length[Unevaluated[1 + 2 + 3]]
Out[8]= 3

Stripping happens after Sequence splicing

In[9]:= Length[Unevaluated[Sequence[a, b]]]
Out[9]= 2

A genuinely held slot keeps the wrapper

In[10]:= Hold[Unevaluated[1 + 2]]
Out[10]= Hold[Unevaluated[1 + 2]]
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]] passes expr to f as if f temporarily held that single argument; the Unevaluated wrapper is then stripped before f's body runs, effectively yielding f[expr] with expr unevaluated.
  • 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]] gives 3 (Length sees the held Plus[1,2,3], not 6).
  • The wrapper is not stripped in a genuinely held slot — when f has HoldAll, or HoldFirst/HoldRest applies to that position — because the argument was never going to be evaluated: Hold[Unevaluated[1+2]] gives Hold[Unevaluated[1+2]], and with HoldAll f, f[Unevaluated[1+2]] gives f[Unevaluated[1+2]].
  • The wrapper is likewise not stripped when the enclosing function has HoldAllComplete (e.g. HoldComplete, or Unevaluated itself).
  • Stripping happens after Sequence flattening, so a Sequence directly inside Unevaluated survives into the argument slot (Length[Unevaluated[Sequence[a, b]]] gives 2).
  • Nested Unevaluated wrappers are stripped one layer per evaluation step.
  • As a top-level expression, Unevaluated[expr] evaluates to itself (because of HoldAllComplete).

Attributes: HoldAllComplete, Protected.

References

See also: HoldAll, HoldFirst, HoldRest, HoldAllComplete, HoldComplete, Sequence

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.