MathGroup Archive 1996

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Re-evaluation of Conditional expressions

  • To: mathgroup at smc.vnet.net
  • Subject: [mg3512] Re: Re-evaluation of Conditional expressions
  • From: withoff (David Withoff)
  • Date: Mon, 18 Mar 1996 01:00:02 -0500
  • Organization: Wolfram Research, Inc.
  • Sender: owner-wri-mathgroup at wolfram.com

Judging from the number of responses to the "Re-evaluation of
Conditional expressions" message, my initial one-paragraph explanation
was clearly inadequate.  I'm sorry if my explanation generated more
confusion than it resolved.  I was originally thinking that this
was just a problem with the meaning of Update, but apparently, at
least for some, there was also a problem with the much more fundamental
question of when and why expression elements are held unevaluated,
and the effect that this has on results.

There are four related things that came up in this discussion that
I would like to comment on:

1) The role of the HoldAll attribute.

In my intial explanation, I neglected to mention the HoldAll attribute.
Dave Wagner has already explained why If needs to at least have the
HoldRest attribute: if the second and subsequent elements in
If[cond, e1, e2, e3] were not held unevaluated, they would be
processed regardless of the value of cond.  This would defeat
the purpose of the If statement, which is to select only one of the
evaluations.

2) Whether or not If needs to hold the first element unevaluated.

As Dave Wagner pointed out, the explanation in (1) does not resolve
the question of whether or not the first element in If should be
held unevaluated.  I am not aware of any overwhelming design
objective to decide this issue, and can easily come up with examples
in which you would want the first element in If to be evaluated,
and examples in which you would not want the first element to be
evaluated.  For reasons that I could elaborate upon separately,
I am currently leaning in favor of not holding the first element
in If unevaluated.  This can be achieved by setting the HoldRest
attribute for If, rather than the HoldAll attribute.  (In the vast
majority of practical programs, it doesn't make any difference.)

3) Use of a delayed assignment does not change the original example

As a reminder, here is the initial example.

In[1]:= y = If[x, 1, 2]

Out[1]= If[x, 1, 2]

In[2]:= x = z

Out[2]= z

In[3]:= y

Out[3]= If[x, 1, 2]

In[4]:= z = True

Out[4]= True

In[5]:= y

Out[5]= If[x, 1, 2]     <==== a result of 1 was expected here.

If you try this example using a delayed assignment (y := If[x, 1, 2])
the behavior will be essentially unchanged.  The expression
If[x, 1, 2] evaluates to itself in In[3], and will not be re-evaluated
unless something inside the expression changes.  The use of
a delayed assignment prevents the initial evaluation of If[x, 1, 2]
during evaluation of the assignment y = If[x, 1, 2], but does not
otherwise change the example.

4) The effect of replacing the HoldAll attribute with HoldRest

Replacing the HoldAll attribute of If with HoldRest may be the easiest
way to get the behavior that was expected in the first place.

In[1]:= ClearAttributes[If, HoldAll]; SetAttributes[If, HoldRest]

In[2]:= y = If[x, 1, 2]

Out[2]= If[x, 1, 2]

In[3]:= x = z

Out[3]= z

In[4]:= y

Out[4]= If[z, 1, 2]

In[5]:= z = True

Out[5]= True

In[6]:= y

Out[6]= 1

Here, If[x, 1, 2] does not evaluate to itself.  After the assignment
to x, it evaluates to If[z, 1, 2].  The subsequent change in the
value of z causes yet another evaluation, since this time, something
explicitly present in the expression changed (the value of z).

I hope that this last point answers the most immediate concerns
that Richard Fateman raised about my explanation.  Specifically,
the change when "If" is replaced by "f" is a consequence of the
fact that "f" doesn't by default hold its elements unevaluated.
If you set the HoldAll attribute for f, and add a rule that causes
f to do something when its first element evaluates to True or False,
the behavior will be identical in this example to the behavior of If.

In[1]:= SetAttributes[f, HoldAll]

In[2]:= f[cond_, e1_, e2_] := e1 /; cond === True

In[3]:= f[cond_, e1_, e2_] := e2 /; cond === False

In[4]:= y=f[z,1,2]

Out[4]= f[z, 1, 2]

In[5]:= z=True;y

Out[5]= 1

In[6]:= z=ww;y

Out[6]= f[z, 1, 2]

Finally, here is a non-technical, somewhat personal note.

Richard Fateman's remark that "evaluation in Mathematica is
rather subtle" brought back bad memories for me of my time in
academia, only this time, to my embarassment, I'm afraid that
I (and others at Wolfram Research) are the teacher.

The bad memory is that most of the time when a teacher said that
something was "subtle" it meant either that the teacher didn't
understand it well enough to explain it clearly, or couldn't be
bothered to explain it clearly.

Well, we really do understand this aspect of Mathematica, and it's
pretty straightforward.  It would be a shame if anyone was left
with the idea that this material is complicated just because no one
bothered to explain it.  The explanation in the Mathematica book
(especially the section on evaluation in the appendix) is, I think,
pretty good, but that of course doesn't mean that there won't ever
be any questions about it.

If there are any remaining questions, please let me know.

Dave Withoff
Research and Development
Wolfram Research

==== [MESSAGE SEPARATOR] ====


  • Prev by Date: Re: More on functions & derivatives
  • Next by Date: Re: Round[1.5] != Round[3/2] = 2 ???
  • Previous by thread: Re: Re-evaluation of Conditional expressions
  • Next by thread: Re: Re-evaluation of Conditional expressions