MathGroup Archive 2001

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

Search the Archive

Re: scope all wrong? in Mathematica 4.1

  • To: mathgroup at smc.vnet.net
  • Subject: [mg31861] Re: scope all wrong? in Mathematica 4.1
  • From: "Alan Mason" <swt at austin.rr.com>
  • Date: Fri, 7 Dec 2001 05:57:00 -0500 (EST)
  • References: <9ul2ft$6m3$1@smc.vnet.net>
  • Sender: owner-wri-mathgroup at wolfram.com

In general, Mathematica has complicated rules for when and how its functions
hold their arguments, which can lead to semantic surprises.  Users can
change these attributes at their own risk.  In particular, the right-hand
side of a SetDelayed such as uu[...] := x is normally not evaluated, and the
left-hand side is normally wrapped in HoldPattern.  Just how these rules
work in conjunction with the pattern matcher is a mystery, but
they definitely are not working correctly in Fateman's first example ---
rr[x_] := Module[{x}, x = 5; Print["x is ", x]].
The system needs to unwrap the various Holds in the right order and process
first the
first argument {...}of Module giving the locals and preempt the pattern
matcher if there is a clash.  Presumably this should be done before
Mathematica's uniqueifying rules (appending $n to local variable names to
make
them unique) are performed.  Could be a timing problem.  The handling of
Hold
and ReleaseHold is tricky and this may explain some other bugs, e.g. why in
version 4.1
Collect[e_, patt_, func] incorrectly releases any Holds present in e.

In view of the above, I think the Fateman's second example, uu[x_?((x = 5;
Print["x is ", x]; True) &)] := x,
actually shows Mathematica doing something correctly :=).  The x_ should
correspond to the x on the right-hand side,
whereas the x in the PatternTest, being on the LHS, should define and/or
update a new variable x separate from
whatever x_ matches.  Also, on a fresh startup of Mathematica v4.1 I get no
extraneous printout.

Fateman's third example, Module[{x}, uu[x_?((x = 5; Print["x is ", x]; True)
&)] := x;  Print["in Module, x is " , x]],
illustrates some interesting behavior when
run repeatedly, as in the following notebook.  I do not find that x is
changed to 5.  However, the printed statements
become more numerous with each subsequent run.  Examination shows that
Mathematica is
defining a new version of uu with each run, parameterized by the current
local name x$9, x$10, etc. for the local x, and is running all the versions.
This is as it should be.
Surprisingly, however, these variables are not
allocated on the stack but seem to be stored on the heap -- one has
access to them and can change them.  I have not been able to
change the global x from 400 to 5, but x$9 is also in essence global (it
didn't disappear from any stack) and if I reassign x$9 to 44, say, and run
the Module[...] again, x$9 *is* changed back to 5. This is not happening to
x, though -- x remains 400.  In a way this is good, since one doesn't expect
the global x to be changed, but it also seems inconsistent since x$9 is just
as global as x . It would appear that local variables in Mathematica are not
treated as such if they parameterize global objects defined inside a
module; instead, the system keeps track of them even after their scope
disappears.
This enables Mathematica to distinguish dynamically between different
instances of, e.g., programmatically generated rules
parameterized by some argument(s), but seems to muddy the distinction
between local and global variables.  Why does Mathematica behave this way,
rather than just plugging the value of x$n directly into the rule and then
letting
x$n go out of scope?  Maybe because in principle it allows the user to
change x$n and
therefore also the rule (this is the essence of RuleDelayed, I suppose); but
users will typically not
know what alias to use for the local variable x in order to change it (the
only way to find this alias is to do a ?uu).  So I wonder
if this hypothetical advantage warrants the apparent inconsistency that I
noted above.


In[1]:=
x = 400
Out[1]=
400
In[2]:=
Module[{x}, uu[x_?((x = 5; Print["x is ", x]; True) &)] := x;
Print["in Module, x is " , x]]
in Module, x is \[InvisibleSpace]x$9
In[3]:=Module[{x}, uu[x_?((x = 5; Print["x is ", x]; True) &)] := x;
Print["in Module, x is " , x]]
x is \[InvisibleSpace]5
x is \[InvisibleSpace]5
in Module, x is \[InvisibleSpace]5
In[4]:=
Module[{x}, uu[x_?((x = 5; Print["x is ", x]; True) &)] := x;
Print["in Module, x is " , x]]
x is \[InvisibleSpace]5
x is \[InvisibleSpace]5
x is \[InvisibleSpace]5
x is \[InvisibleSpace]5
in Module, x is \[InvisibleSpace]5
In[5]:=
Module[{x}, uu[x_?((x = 5; Print["x is ", x]; True) &)] := x;
Print["in Module, x is " , x]]
x is \[InvisibleSpace]5
x is \[InvisibleSpace]5
x is \[InvisibleSpace]5
x is \[InvisibleSpace]5
x is \[InvisibleSpace]5
x is \[InvisibleSpace]5
in Module, x is \[InvisibleSpace]5
In[6]:=
?uu
Global`uu
\!\(\*
  InterpretationBox[GridBox[{
        {GridBox[{
              {\(uu[x_?\((\((x$9 = 5; Print["x is ", x$9]; True)\) &)\)] :=
                  x\)},
              {" "},
              {\(uu[x_?\((\((x$10 = 5; Print["x is ", x$10]; True)\) &)\)]
:=
                  x\)},
              {" "},
              {\(uu[x_?\((\((x$11 = 5; Print["x is ", x$11]; True)\) &)\)]
:=
                  x\)},
              {" "},
              {\(uu[x_?\((\((x$12 = 5; Print["x is ", x$12]; True)\) &)\)]
:=
                  x\)}
              },
            GridBaseline->{Baseline, {1, 1}},
            ColumnWidths->0.999,
            ColumnAlignments->{Left}]}
        },
      GridBaseline->{Baseline, {1, 1}},
      ColumnAlignments->{Left}],
    Definition[ "uu"],
    Editable->False]\)
In[7]:=
x$9 = 44
Out[7]=
44
In[8]:=
Module[{x}, uu[x_?((x = 5; Print["x is ", x]; True) &)] := x;
Print["in Module, x is " , x]]
(snip--AGM)
In[9]:=
{x, x$9}
Out[9]=
{400,5}

Alan

"Richard Fateman" <fateman at cs.berkeley.edu> wrote in message
news:9ul2ft$6m3$1 at smc.vnet.net...
> Consider the mathematica definition
>
> rr[x_] := Block[{x}, x = 5; Print["x is ", x]]
>
>   what do you expect here?
>
> rr[z]  -->   x is 5  is printed.
> but you might not expect
>
> rr[4]  -->    "Block::"lvsym": "Local variable specification{4} contains 4
> which is not a symbol or an assignment to a symbol."
>
> If you use Module instead of Block, you get
> the same.
>
> However,
> Block[{x = 4}, Block[{x}, x = 5; Print["x is ", x]]]
>
> prints   x is 5
>
> Using pattern matching for
> substituting 4 for x in rr[4] even when x is bound seems
> to be counter to what most programming language designers
> would expect.
>
>
>
> Now look at
>
> uu[x_?((x = 5; Print["x is ", x]; True) &)] := x
>
> Usually when one defines a program, nothing is printed.
> Here, we get
> x is 5
> 5
> x is 5
>
> If we do this:
> x =400
> uu[70]
>      x is 5  printed
> the value returned is 70
> and the global x is 5.
>
> Try this:
> Module[{x}, uu[x_?((x = 5; Print["x is ", x]; True) &)] := x;
>    Print["in Module, x is " , x]]
>
> The expectation in a system supporting lexical scope
> with Module
> is that no use of x inside the module would escape.
> But it does.  The global x is set to 5.
>
>
> The reason this all came up is in correspondence suggesting
> that programs in one computer algebra system could be
> translated into another.  If systems are semantically
> "surprising", it is more difficult. I wonder how much
> of mathematica internally depends on wrong scope, or how
> much of the code is susceptible to bugs because of unexpected
> capture of names.  (I suspect that this has caused a proliferation
> of package names e.g. MySecretNameSpace`x   in Mathematica
> routines).
>
> RJF
>
>





  • Prev by Date: Re: scope all wrong? in Mathematica 4.1
  • Next by Date: Re: scope all wrong? in Mathematica 4.1
  • Previous by thread: Re: scope all wrong? in Mathematica 4.1
  • Next by thread: Re: scope all wrong? in Mathematica 4.1