       Re: Is this a bug?

• To: mathgroup at smc.vnet.net
• Subject: [mg32066] Re: Is this a bug?
• From: "Alan Mason" <swt at austin.rr.com>
• Date: Fri, 21 Dec 2001 03:57:47 -0500 (EST)
• References: <9vs8ph\$g1d\$1@smc.vnet.net>
• Sender: owner-wri-mathgroup at wolfram.com

"Paul van Wamelen" <wamelen at math.lsu.edu> wrote in message
news:9vs8ph\$g1d\$1 at smc.vnet.net...
> Is the following a bug?
>
> Mathematica 4.1 for Sun Solaris
> Copyright 1988-2000 Wolfram Research, Inc.
>  -- Motif graphics initialized --
>
> In:= k[x_] := Module[{},Print["hallo world"];x];
>
> In:= a = 0;
>
> In:= a[k]++
> hallo world
> hallo world
>
> Out= 0
>
>
> I would have expected only one "hallo world" and it would seem to be
> more efficient to only evaluate the k once...
>
> The above example is not important but in the form below it had me
> baffled for a while:
>
> In:= tst[n_] := Module[{a},
>   a = a = 0;
>   Do[a[Random[Integer,{0,1}]]++,{n}];
>   {a,a}]
>
> In:= tst
>
> Out= {24, 24}
>
> (Does not add up to 50!)
>
> Thanks!

Hello Paul,
I think you've hit the jackpot with this example!

Part The First:
No, it's not a bug; you're seeing the standard Mathematica evaluation
mechanism at work.  It is not special to ++.  On encountering a[k]++,
Mathematica first looks at a[k] and evaluates it, then adds 1 to the
result and looks at that, triggering another evaluation .  Note that if
a[k]++ is replaced by k++, there is only one evaluation and only one
print statement results.

Basically, Mathematica is proceeding very simple-mindedly, as can be seen by
doing a Trace, see following notebook. It first evaluates k, then plugs
it into a; but then it increments a[k] (not a directly!), causing a
second bout of evaluation and hence a second print statement (a side
effect).  Thus Mathematica treats a[k]++ and a++ differently, even
though k is currently 5.  Why might this be desirable?  Because k is
SetDelayed.  If I change it later k will no longer be 5 in general, but
the statement a[k]++ (e.g., on the right-hand side of a delayed rule or
assignment) will be correctly updated and a[?] will be incremented, where ?
is the new (current) value of k.  You could say that Mathematica is
hyperdynamic, always allowing for possible future changes to rules and their
side effects, at the cost of some extra evaluations.  If Mathematica were to
compute a[k]++ in the way you suggest, it would amount to assuming that
++ is an atomic operation, during which no rules (in particular, k) could
change.  But even if ++ were atomic, such a treatment would be inconsistent
with Mathematica's general view of things.

Part The Second:
Yes, it is a bug.   Your second example, with k replaced by Random, gives a
striking illustration of when Mathematica's behavior is EXTREMELY
UNDESIRABLE!  Why?  Because people don't expect it, to say the least.  By
its very nature, Random[] is going to defeat Mathematica's strategy because
it differs at each call.  Thus the double call of Random that Mathematica
makes can give inconsistent results -- the value it returns the first time
need not be the same  the second time.  Thus your example is special to
Random and similar hypervolatile functions.  For normal k, Mathematica's
approach works fine.

By the way, I think your example meets Withoff's criterion of a situation
where Mathematica's handling of SetDelayed (with "extra" evaluations not
done "in private") has bad practical consequences, although again,
mercifully limited to Random (but extending also, I suppose, to any function
k that calls Random). See David Withoff's post (second of four) "Re Re Scope
all wrong...", Dec. 10, 2001 in MathGroup Archives.

The following notebook has two parts.  The second does a Trace of tst and
I've commented the "smoking gun".

Alan

In:=
k[x_] := Module[{},Print["hallo world"];x];
a = 0;
Out=
\!\(Null\^2\)
In:=
a[k]
hallo world
Out=
0
In:=
Trace[a[k]++]
hallo world
hallo world
Out=
{a[k]++,{{k,
Module[{},Print[hallo world];5],{Print[hallo world];
5,{Print[hallo world],{MakeBoxes[hallo world,StandardForm],
"hallo world"},Null},5},5},a,
0},{a[k]=
1,{{k,Module[{},Print[hallo world];5],{Print[hallo world];
5,{Print[hallo world],{MakeBoxes[hallo world,StandardForm],
"hallo world"},Null},5},5},a},1},0}
In:=
a
Out=
1
(**************************************************************)
In:=
tst[n_] := Module[{a},
a = a = 0;
Do[a[Random[Integer,{0,1}]]++;Print[{a, a}],{n}];
Return[ {a,a}]]

In:=
Trace[tst]
(*tst*)

{1,0}

{2,0}

{2,3} (* WHAT?!  YOU'RE KIDDING! *)

{4,3}

{4,5}

Out=
{tst,Module[{a\$},a\$=a\$=0;
Do[a\$[Random[Integer,{0,1}]]++;Print[{a\$,a\$}],{5}];
Return[{a\$,a\$}]],{a\$88=a\$88=0;
Do[a\$88[Random[Integer,{0,1}]]++;Print[{a\$88,a\$88}],{5}];
Return[{a\$88,a\$88}],{{a\$88=0,0},a\$88=0,
0},{Do[a\$88[Random[Integer,{0,1}]]++;
Print[{a\$88,a\$88}],{5}],{a\$88[Random[Integer,{0,1}]]++;
Print[{a\$88,

a\$88}],{a\$88[Random[Integer,{0,1}]]++,{{Random[Integer,{0,1}],
0},a\$88,
0},{a\$88[Random[Integer,{0,1}]]=1,{{Random[Integer,{0,1}],0},
a\$88},1},0},{{{a\$88,1},{a\$88,0},{1,0}},
Print[{1,0}],{MakeBoxes[{1,0},StandardForm],
RowBox[{{,RowBox[{1,,,0}],}}]},Null},
Null},{a\$88[Random[Integer,{0,1}]]++;
Print[{a\$88,

a\$88}],{a\$88[Random[Integer,{0,1}]]++,{{Random[Integer,{0,1}],
0},a\$88,
1},{a\$88[Random[Integer,{0,1}]]=2,{{Random[Integer,{0,1}],0},
a\$88},2},1},{{{a\$88,2},{a\$88,0},{2,0}},
Print[{2,0}],{MakeBoxes[{2,0},StandardForm],
RowBox[{{,RowBox[{2,,,0}],}}]},Null},
Null},{a\$88[Random[Integer,{0,1}]]++;
Print[{a\$88,

a\$88}],{a\$88[Random[Integer,{0,1}]]++,{{Random[Integer,{0,1}],  (*
SMOKING GUN HERE *)
0},a\$88,
2},{a\$88[Random[Integer,{0,1}]]=3,{{Random[Integer,{0,1}],1},
a\$88},3},2},{{{a\$88,2},{a\$88,3},{2,3}}, (* OH REALLY?
*)
Print[{2,3}],{MakeBoxes[{2,3},StandardForm],
RowBox[{{,RowBox[{2,,,3}],}}]},Null},
Null},{a\$88[Random[Integer,{0,1}]]++;
Print[{a\$88,

a\$88}],{a\$88[Random[Integer,{0,1}]]++,{{Random[Integer,{0,1}],
1},a\$88,
3},{a\$88[Random[Integer,{0,1}]]=4,{{Random[Integer,{0,1}],0},
a\$88},4},3},{{{a\$88,4},{a\$88,3},{4,3}},
Print[{4,3}],{MakeBoxes[{4,3},StandardForm],
RowBox[{{,RowBox[{4,,,3}],}}]},Null},
Null},{a\$88[Random[Integer,{0,1}]]++;
Print[{a\$88,

a\$88}],{a\$88[Random[Integer,{0,1}]]++,{{Random[Integer,{0,1}],
0},a\$88,
4},{a\$88[Random[Integer,{0,1}]]=5,{{Random[Integer,{0,1}],1},
a\$88},5},4},{{{a\$88,4},{a\$88,5},{4,5}},
Print[{4,5}],{MakeBoxes[{4,5},StandardForm],
RowBox[{{,RowBox[{4,,,5}],}}]},Null},Null},
Null},{{{a\$88,4},{a\$88,5},{4,5}},Return[{4,5}]},Return[{4,5}]},
Return[{4,5}],{4,5}}

• Prev by Date: Re: Font problems w SuSE 7.3
• Next by Date: Re: NDSolve problem with piecewise functions
• Previous by thread: Re: Is this a bug?
• Next by thread: Re: Is this a bug?