Re: Re: Module inside Module. Conflict between inner Module local variable
- To: mathgroup at smc.vnet.net
- Subject: [mg79724] Re: [mg79590] Re: Module inside Module. Conflict between inner Module local variable
- From: "Jean-Marc Gulliet" <jeanmarc.gulliet at gmail.com>
- Date: Thu, 2 Aug 2007 04:01:15 -0400 (EDT)
- References: <200707301046.GAA02035@smc.vnet.net>
On 7/30/07, Clifford Martin <camartin at snet.net> wrote: > 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? Hi Cliff, I am pleased to hear that my explanation was clear enough. About books or tutorials, I have many projects in mind but nothing serious about a book on Mathematica programming. Cheers, Jean-Marc > 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 > > > > > > > >