Unevaluated subtleties

• To: mathgroup at smc.vnet.net
• Subject: [mg92683] Unevaluated subtleties
• From: magma <maderri2 at gmail.com>
• Date: Fri, 10 Oct 2008 04:35:56 -0400 (EDT)

```I was thinking at how to measure the Length of an expression in the
form that is entered by the user.
The way to do it is:

Length[Unevaluated[expr]]

For example

Length[Unevaluated[2+5]]

gives

2

which is what I wanted since 2+5 is really Plus[2,5], a function with
2 arguments.
So far so good.

Then I started to experiment a bit with Unevaluated and I soon
discovered that it behaves curiously .

To peek at the inner workings of Mathematica I always like to switch

On[]

and then try remembering to switch

Off[]

again very quickly, before doing something silly.
So look at this:

Type:

On[]
Unevaluated[2+5]//Length
Off[]

and you get (line numbering added for clarity)

On::trace: On[] --> Null. >>
Length::trace: Length[Unevaluated[2+5]] --> Length[2+5]. >>        (*
Line 1 *)
Length::trace: Length[2+5] --> 2.
>>                                           (* Line 2 *)

Out[269]= 2

Which is what we got before.
Now let's see what happens if we split the oneliner expression

Unevaluated[2+5]//Length

in 2 parts. Normally this should have no consequences, but in this
case...

On[]
Unevaluated[2+5]
%//Length
Off[]

On::trace: On[] --> Null. >>

Out[280]= Unevaluated[2+5]

Out::trace: % --> Out[\$Line-1]. >>
\$Line::trace: \$Line --> 281. >>
Plus::trace: \$Line-1 --> 281-1. >>
Plus::trace: 281-1 --> 280. >>
Out::trace: Out[\$Line-1] --> %280. >>
Out::trace: %280 --> Unevaluated[2+5]. >>
Length::trace: Length[%] --> Length[Unevaluated[2+5]]. >>
Length::trace: Length[Unevaluated[2+5]] --> 1.
>>                       (* Line 3 *)

Out[281]= 1

It gives a  different result!
This is vaguely hinted at in the Unevaluated info page under
Properties & Relations

"Unevaluated works only where it appears; it is not propagated"
This probably means that it is not wise to split things up when
dealing with Unevaluated.
Yet, how does Mathematica know?
Compare line 1  with line 3 : both start with the same
Length[Unevaluated[2+5]], yet the result is different!
I find this a bit amazing. Obviously something is going on behind the
scenes that is not revealed with a simple On[].
Look now at Line 2.
Isn't that amazing? A simple looking Length[2+5] is evaluated as 2.
It should be either 0, because Length[7] is 0 or it should be 1, if we
imagine some invisible wrapper (HoldForm?, Unevaluated?) protecting
2+5.
Length has no special attributes, yet 2+5 is taken as Plus[2,5] and
its length evaluates to 2.
However all of this is totally invisible.

Just for comparison type

In[283]:= On[]
Length[2+5]
Off[]

On::trace: On[] --> Null. >>
Plus::trace: 2+5 --> 7. >>
Length::trace: Length[2+5] --> Length[7]. >>                       (*
Line 4 *)
Length::trace: Length[7] --> 0. >>

Out[284]= 0

Compare line 2 above with Line 4 here, they start the same, yet they
end up very differently.

All this suggests to me that either Unevaluated has a very odd and
unique non-standard evaluation or that it has some undocumented side
effects at least at a local (ie. temporary) level.