Re: Evaluate/Module[Correction]
- To: mathgroup at smc.vnet.net
- Subject: [mg16133] Re: Evaluate/Module[Correction]
- From: "Allan Hayes" <hay at haystack.demon.co.uk>
- Date: Sat, 27 Feb 1999 03:23:05 -0500
- References: <7atq9s$7kr@smc.vnet.net> <7b32nl$1ss@smc.vnet.net>
- Sender: owner-wri-mathgroup at wolfram.com
Paul Abbott, in an email that will be appearing as a posting, writes
> I'm not convinced by your explanation.
and gives the examples reproduced below the line
****************************************
Yes: thanks Paul
The account that I gave of the evaluation of CompoundExpression[...] is
incorrect (I correct it below); but I think that the rest of the explanation
is OK.
Normally, CompoundExpression evaluates its entries in sequence and then
gives the value of the last one. However, since it has the attribute HoldAll
this evaluation is under the control of the programmer and if some entries
are wrapped in Evaluate[ ] they will be evaluated first in order, and then
the other entries will be evaluated in order.
The last entry in the resulting expression is returned as the value of the
compound expression,
So, writing ei* for the value of ei, we get the following steps
CompoundExpression[e1, Evaluate[e2], Evaluate[e3], e4]
CompoundExpression[e1, e2*, Evaluate[e3], e4]
CompoundExpression[e1, e2*, e3*, e4]
CompoundExpression[e1*, e2*, e3*, e4]
CompoundExpression[e1*, e2*, e3*, e4*]
e4*
I tripped up because of a misinterpretation of the following example:
In[7]:=
pr =.
In[8]:=
CompoundExpression[ {pr = Print, pr[2]}, Evaluate[{Print[1], pr[3]}] ]
1
2
3
Out[8]=
{Null, Null}
The printout shows the order of evaluation; and the 3 lead me to believe
that the second entry had been evaluated a second time inside
CompoundExpression[ ..]; and so to think that all entries wrapped in
Evaluate were so re-evaluated. However, the following shows that this is not
so, because no 3 is printed. What in fact had happened was that {Print[1],
pr[3]} is returned by CompoundExpression and is then evaluated.
In[62]:=
pr =.
CompoundExpression[ {pr = Print, pr[2]}, Evaluate[{Print[1], pr[3]}, 4 ]
1
2
4
Other points:
>Incidentally, in your code
>
>tmp = x^2 +1;
>
>Module[{x=4}, tmp=tmp-1;Print[tmp]; Evaluate[tmp]]
>
>Module has no effect:
>- the x are renamed x$n (where n is the ModuleNumber); but this is done
>before the body
> tmp=tmp-1;Print[tmp]; Evaluate[tmp]
>is evaluated, so, only the displayed x is renamed.
>- then the assigment x$n = 4 is made.
>- after this the body evaluates to x^2+1 but this involves x, not x$n, so
>the assignment has no effect.
And taking up my suggestion to Evaluate the body we get
In[1]:=
tmp = x^2 +1;
In[2]:=
Module[{x=4}, Evaluate[tmp=tmp-1;Print[tmp]; Evaluate[tmp]]]
x^2
Out[2]=
17
Because, overiding the HoldAll attribute of Module, first the body
evaluates to x^2 +1 ( printing x^2 on the way) giving
Module[{x=4}, x^2+1]
Then we get the local varable form
Module[{x$n=4}, x$n^2+1]
The assignment x$n=4 is then made and x$n^2+1] therefore evaluates to 4^2+1,
that is 17.
A variant of this is:
In[3]:=
tmp = x^2 +1;
In[4]:=
Module[{x=4}, Evaluate[tmp=tmp-1;Print[tmp]; tmp]]
x^2
Out[4]=
16
And, also , with yet another outcome,
In[5]{=
tmp = x^2 +1;
In[6]:=
x=4; tmp=tmp-1;Print[tmp]; Evaluate[tmp]
16
Out[6]=
17
The following is an account of the evaluation of Paul's inputs, using these
ideas. I abbreviate CompoundExpression to CE
In[7]:=
a = 1; a = a - 1; Evaluate[a]
Out[7]=
0
Evaluation steps
CE[a = 1, a = a - 1, a]
CE[1, a = a - 1, a] with a =1 stored
CE[1, a = 1- 1, a ] ,,
CE[1, a = 0, a ] ,,
CE[1, 0, a ] with a=0 stored
a ,,
0
Note: the final evaluation of a to 0 above is outside CE[..] - because
the last entry had already been evaluated to a inside CE[...]
Without Evaluate:
In[8]:=
a = 1; a = a - 1; a
Out[8]=
0
Evaluation steps
CE[a = 1, a = a - 1, a]
CE[1, a = a - 1, a] a = 1 stored
CE[1, a = 1- 1, a ] ,,
CE[1, a = 0, a ] ,,
CE[1, 0, a ] a = 0 stored
CE[1,0,0] ,,
0
In[9]:=
Module[{a = 1}, a = a - 1; Evaluate[a]]
Out[9]=
1
Evaluation steps
Module[{a$n = 1}, a$n = a$n - 1; Evaluate[a$n]]
CE[ a$n = a$n - 1, Evaluate[a$n]], a$n = 1 stored
CE[a$n =a$n - 1,1] ,,
CE[a$n =1 - 1,1] ,,
CE[a$n =0, 1 ] ,,
CE[0,1] a$n = 0 stored
In[10]:=
Module[{a = 1}, a = a - 1; a]
Out[10]=
0
Evaluation steps
Module[{a$n = 1}, a$n = a$n - 1; a$n]
CE[a$n = a$n - 1, a$n] a$n = 1 stored
CE[a$n = 1 - 1, a$n] ,,
CE[a$n = 0, a$n ] ,,
CE[ 0, a$n ] a$n = 0 stored
CE[0, 0 ] ,,
0
---------------------
Allan Hayes
Mathematica Training and Consulting
Leicester UK
www.haystack.demon.co.uk
hay at haystack.demon.co.uk
Voice: +44 (0)116 271 4198
Fax: +44 (0)870 164 0565
****************************************************************************
************
Allan Hayes wrote:
> Neither problem invoves Module; both are due to how expressions like
> e1;e2;e3;e4 (FullForm CompoundExpression[e1,e2, e3,e4]
> evaluate
>
> Normally, CompoundExpression evaluates its entries in sequence and then
> gives the value of the last one. However, since it has the attribute
HoldAll
> this evaluation is under the control of the programmer and if some entries
> are wrapped in Evaluate[ ] they will be evaluated first *and* the the
> resulting expression will then be evaluated as usual
> So, writing ei* for the value of ei, we get the following steps
>
> CompoundExpression[e1, Evaluate[e2], Evaluate[e3], e4]
> CompoundExpression[e1, e2*, Evaluate[e3], e4]
> CompoundExpression[e1, e2*, e3*, e4] (*restart!*)
> CompoundExpression[e1*, e2*, e3*, e4]
> CompoundExpression[e1*, e2**, e3*, e4]
> CompoundExpression[e1*, e2**, e3**, e4]
> CompoundExpression[e1*, e2**, e3**, e4*]
> e4*
I'm not convinced by your explanation. Consider the following
CompoundExpressions:
In[1]:= a = 1; a = a - 1; Evaluate[a]
Out[1]= 0
In[2]:= a = 1; a = a - 1; a
Out[2]= 0
Now, compare these results with a simple Module:
In[3]:= Module[{a = 1}, a = a - 1; Evaluate[a]]
Out[3]= 1
In[4]:= Module[{a = 1}, a = a - 1; a]
Out[4]= 0
Note that both Module and CompoundExpression have the HoldAll Attribute:
In[5]:= Attributes[Module]
Out[5]= {HoldAll, Protected}
In[6]:= Attributes[CompoundExpression]
Out[6]= {HoldAll, Protected, ReadProtected}
Using Trace does give some idea as to what is going on:
In[7]:= Trace[a = 1; a = a - 1; Evaluate[a]]
Out[7]= {{a, 0}, a = 1; a = a - 1; 0, {a = 1, 1},
{{{a, 1}, 1 - 1, 0}, a = 0, 0}, 0}
In[8]:= Trace[a = 1; a = a - 1; a]
Out[8]= {a = 1; a = a - 1; a, {a = 1, 1},
{{{a, 1}, 1 - 1, 0}, a = 0, 0}, {a, 0}, 0}
In[9]:= Trace[Module[{a = 1}, a = a - 1; a]]
Out[9]= {Module[{a = 1}, a = a - 1; a], {a$9 = 1, 1},
{a$9 = a$9 - 1; a$9, {{{a$9, 1}, 1 - 1, 0}, a$9 = 0, 0},
{a$9, 0}, 0}, 0}
In[10]:= Trace[Module[{a = 1}, a = a - 1; Evaluate[a]]]
Out[10]= {Module[{a = 1}, a = a - 1; Evaluate[a]], {a$10 = 1, 1},
{{a$10, 1}, a$10 = a$10 - 1; 1,
{{{a$10, 1}, 1 - 1, 0}, a$10 = 0, 0}, 1}, 1}
Cheers,
Paul
____________________________________________________________________
Paul Abbott Phone: +61-8-9380-2734
Department of Physics Fax: +61-8-9380-1014
The University of Western Australia
Nedlands WA 6907 mailto:paul at physics.uwa.edu.au
AUSTRALIA http://www.physics.uwa.edu.au/~paul
God IS a weakly left-handed dice player
____________________________________________________________________