MathGroup Archive 2007

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

Search the Archive

Re: Re: Module inside Module. Conflict between inner Module local variable

  • To: mathgroup at smc.vnet.net
  • Subject: [mg79602] Re: [mg79590] Re: Module inside Module. Conflict between inner Module local variable
  • From: Clifford Martin <camartin at snet.net>
  • Date: Tue, 31 Jul 2007 06:03:22 -0400 (EDT)

Jean-Marc,

I just wanted to say what a very precise description of how Mathematica works as a programming language. It was quite illuminating.  Is there any thought in your mind about writing a book or long tutorial?

Regards,

Cliff


Jean-Marc Gulliet <jeanmarc.gulliet at gmail.com> wrote: 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
> 
> 


  • Prev by Date: Double Integration involving Struve and Neumann functions
  • Next by Date: Re: A cell style question
  • Previous by thread: Re: Module inside Module. Conflict between inner Module local variable
  • Next by thread: An old question on locators