MathGroup Archive 2004

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

Search the Archive

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


  • Prev by Date: Re: Baffled By Underscore Pattern Matching
  • Next by Date: Re: clarification. Re: one liner for a function?
  • Previous by thread: RE: Re: Defining a function in module problem?
  • Next by thread: When/why is Denominator[p/q] != q?