The tutorial I linked to has this list:
- Evaluate the head of the expression.
- Evaluate each element in turn.
- Apply transformations associated with the attributes Orderless, Listable, and Flat.
- Apply any definitions that you have given.
- Apply any built-in definitions.
- Evaluate the result.
It also states:
As discussed in "Associating Definitions with Different Symbols", you can associate definitions with symbols either as upvalues or downvalues. The Wolfram System always tries upvalue definitions before downvalue ones.
Then, for additional clarification,
Definitions associated with g
are applied before definitions associated with f
in the expression f[g[x]]
.
and
in a sequence of elements, upvalues associated with earlier elements take precedence over those associated with later elements.
A special symbol is Sequence
. It is flattened automatically by the evaluator. I am not sure about the order of operations related to Sequence, but a nice way to track is with On[]
and Off[]
. Do this in a command line session only, otherwise recent M versions will produce a flood of messages.
For example, define f[x_, y_, z___] := f[x + y, z]
, then evaluate On[]
, then
In[11]:= f[Sequence[1,2], 3]
f::trace: f[Sequence[1, 2], 3] --> f[1, 2, 3].
f::trace: f[1, 2, 3] --> f[1 + 2, 3].
Plus::trace: 1 + 2 --> 3.
f::trace: f[1 + 2, 3] --> f[3, 3].
f::trace: f[3, 3] --> f[3 + 3].
Plus::trace: 3 + 3 --> 6.
f::trace: f[3 + 3] --> f[6].
Out[11]= f[6]
What we see here is that Sequence
is flattened out before any of f
's transformation rules are applied.
Now you can tracing off with Off[]
.
I find this a clearer representation of what is happening than what can be obtained with the Trace
functions. See also https://mathematica.stackexchange.com/q/29339/12
Finally, there are the Hold*
attributes. These prevent the evaluation of arguments (second bullet point in first list).
When the evaluator encounters an expression that has a head with the HoldAll
attribute, it does not evaluate or examine its arguments, except for one thing: it checks for the presence of Evaluate
as a direct (first-level) argument, and if it finds one, it evaluates it. This is again a special rule.
Finally, there is Unevaluated
, which is explained on its doc page:
f[Unevaluated[expr]]
effectively works by temporarily setting attributes so that f
holds its argument unevaluated, then evaluating f[expr]
.
For a practical introduction to working with Hold
, Unevaluated
and the Hold*
attributes, see http://library.wolfram.com/infocenter/Courseware/377/