RE: Defining a function in module problem?
- To: mathgroup at smc.vnet.net
- Subject: [mg46018] RE: [mg45975] Defining a function in module problem?
- From: "Wolf, Hartmut" <Hartmut.Wolf at t-systems.com>
- Date: Tue, 3 Feb 2004 03:20:48 -0500 (EST)
- Sender: owner-wri-mathgroup at wolfram.com
>-----Original Message----- >From: jflanigan at netzero.net [mailto:jflanigan at netzero.net] To: mathgroup at smc.vnet.net >Sent: Saturday, January 31, 2004 11:21 AM >To: mathgroup at smc.vnet.net >Subject: [mg46018] [mg45975] Defining a function in module problem? > > >why does this > >a[x_] := Module[{f, g}, g = z/3; f = Function[z, Evaluate[g]]; f[x]] > >produce > >a[1] = z/3 > >instead of > >a[1]=1/3 > >I don't understand the philosophy here. > >thanks in advance. > Let's consider the most simple case first g = z/3; f = Function[z, g]; Scan[Information, Hold[g, f]] f[1] // Trace Function has the HoldAll attribute; hence the body of the function defined just refers to the variable g. When applied to an argument just the value of this variable g is retrieved, which at time of execution -- g is evaluated only after the argument z has been substituted "textually" (lambda semantics) in the body, such now -- is z/3, where z is an undefined global variable. When you want to evaluate g within Function to incorporate its value at the time of definition of the function, use Evaluate: g = z/3; f = Function[z, Evaluate[g]]; Scan[Information, Hold[g, f]]; f[1] // Trace You see, g evaluates to z/3 when the Function is defined. Such for the expression z/3 within the body, z ist bound to the argument. This is quite the same as if we had defined (* f = Function[z, z/3] *) The result of the application of the function to an argument arg is arg/3; with argument == 1 this is 1/3. Now introducing Module Module[{f, g}, g = z/3; f = Function[z, g]; Scan[Information, Hold[g, f]]; f[1] // Trace] Module changes the names g, f to g$34, f$34 (say, for this instance of Module only), The value of g$34 again is z/3, z being an undefined global variable . The evaluation is quite similar to the first case above, the body of the function refers to variable g$34 which finally turns out to evaluate to z/3, z global. Also, due to the scoping mechanisms of Mathematica the formal (lambda) variable z within Function had been renamed to z$, but this was of no (additional) consequences here. But this now becomes decisive in your example Module[{f, g}, g = z/3; f = Function[z, Evaluate[g]]; Scan[Information, Hold[g, f]]; f[1] // Trace] g and f now are renamed to g$35, f$35, the value of g$35 still is z/3; z global, undefined. Here now, as in the second case above, inside the definition of the function, g$35 gets substituted by z/3. But now the formal (lambda) variable z of Function had been renamed to z$ prior, hence z in the body is not bound to the argument (the substitution z -> z$ has been made before the evaluation of g). The idea behind this behaviour is to supply Lexical Soping for Mathematica. Lexical Scoping has been considered to be more easy for writing and reading/understanding code, hence to be preferable for programming. To Mathematica the concept was added later by this renaming scheme. It appears not to be perfect and has repeatedly been critized through the years; your example may constitute such a point. However, when problems of this kind occur, there is a strong indication, that something is worth considering with the meaning (semantics) of your code. If you still want to do this, you have an option: just use Block. It seems to be more a case of occasional disturbance when being used to other programming languages. Best however is to accept it for Mathematica as it is, reading in the book occasionally. Then no practical problems will arise. -- Hartmut Wolf