Re: Module inside Module. Conflict between inner Module local variable
- To: mathgroup at smc.vnet.net
- Subject: [mg79590] Re: Module inside Module. Conflict between inner Module local variable
- From: Jean-Marc Gulliet <jeanmarc.gulliet at gmail.com>
- Date: Mon, 30 Jul 2007 06:46:20 -0400 (EDT)
- Organization: The Open University, Milton Keynes, UK
- References: <f8h4k8$6s5$1@smc.vnet.net>
Nasser Abbasi wrote:
> This Mathematica 6.0.1
>
> I just found out that I can't declare a local variable inside a Module
> to be the same name as an input parameter for the outer module.
>
> foo[i_] := Module[{},
>
> boo[] := Module[{i = 1},
> Print[i];
> ];
>
> boo[];
> ]
>
> It seems an inner Module is being treated on the same level as the
> outer module as far are variable scope is concerned. When I call
> foo[5] for example, the local variable 'i' for boo[] was set to 5,
> when it was supposed to be LOCAL to boo[] ! It looks like local
> variables to inner modules are treated just like they are local
> variables to the outer module.
The problem is that you reason not in Mathematica language but you stick
programming concepts from other languages. Think of Mathematica as a
rewriting engine. In Mathematica there are no such things as variables,
local variables, or calling of a function. However, there are symbols,
expression (symbolic expression in the parlance of LISP/Scheme family),
and evaluation of expressions.
When you evaluate the expression f[5], Mathematica does not evaluate the
body of the expression first. It create a rule i -> 5 and apply it on
the right-hand side of the expression (at this stage, think of the
expression as just a string of characters that is being processed by
some transformation rules). That is the RHS of foo becomes
Module[{}, boo[] := Module[{5 = 1}, Print[5]; ]; boo[]; ]
Only then the resulting expression is evaluated. boo[] is evaluated and
Mathematica notice that there is an erroneous attempt to modify the
value of an atomic expression Set[5, 1]. So it issues an error message
and stops the evaluation process.
foo[i_] := Module[{}, boo[] := Module[{i = 1}, Print[i]; ]; boo[]; ]
foo[5]
Module::lvset: Local variable specification {5=1} contains 5=1, which \
is an assignment to 5; only assignments to symbols are allowed. >>
Also, Mathematica is a Computer Algebra System {CAS), which means that
as with any CAS it can -- and had been designed for -- process symbols.
In the definition of the arguments of f, f[i_], _ (or Blank pattern in
full form) just say that one and only one expression is required,
without constraints nor restrictions of any kink on it, so, in
particular, it does not need to be a number. By adding i in front of the
pattern, you just name it: there no type associated with it, no memory
allocated or reserve for it.
foo[s]
1
Why does this work? Following the rewrite-rule processing, the function
foo is first transformed in
Module[{}, boo[] := Module[{s = 1}, Print[s]; ]; boo[]; ]
expression that can be evaluated further.
> I understand that one can't make a local variable with the same name
> as the argument, but boo[] above is supposed to be a separate module
> (even though it is an inner module) except its scope is limited to
> inside foo[].
Wrong. Since you have not declared the name boo at the beginning of the
module -- within the empty parentheses --, the symbol boo is /never/
localized and after the first evaluation of the function foo, boo is
available at the global level. In other word, as written, the first
module construct is totally useless: it does not localize anything, it
does not protect anything, it does nothing.
Below, we use your original definition.
In[1]:= Clear[foo,boo]
foo[i_] := Module[{}, boo[] := Module[{i = 1}, Print[i]; ]; boo[]; ]
In[2]:= ?foo
Global`foo
foo[i_]:=Module[{},boo[]:=Module[{i=1},Print[i];];boo[];]
Nothing has been evaluated yet; boo has no definition at the global level.
In[3]:= ?boo
Global`boo
Now we evaluate foo.
In[4]:= foo[s]
1
and boo is visible and accessible in the global context.
In[5]:= ?boo
Global`boo
boo[]:=Module[{s=1},Print[s];]
In[6]:= boo[]
1
Below, we localize the symbol boo.
In[7]:= Clear[foo,boo]
foo[i_] := Module[{boo}, boo[] := Module[{i = 1}, Print[i]; ]; boo[]; ]
In[9]:= foo[s]
1
Having evaluated foo, boo is not visible in the global context and it is
not accessible directly.
In[10]:= ?boo
Global`boo
In[11]:= boo[]
Out[11]= boo[]
> So I do not see why the above would not be allowed. This restriction
> does not seem to make too much sense to me.
The issue is not about to be or not to be allowed. The issue is about to
understand the fundamental rules of the evaluation and rewrite
processes.The following sections of _The Mathematica Book_ should be of
a great help.
"Section A.4: Evaluation"
http://documents.wolfram.com/mathematica/book/section-A.4
"Section A.5: Patterns and Transformation Rules"
http://documents.wolfram.com/mathematica/book/section-A.5
Regards,
Jean-Marc
> Is there a trick to make the above legal without moving boo[] outside
> of foo[] ?
>
> thanks,
> Nasser
>
>