MathGroup Archive 2000

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

Search the Archive

Re: Defining a function within a module

  • To: mathgroup at smc.vnet.net
  • Subject: [mg22529] Re: [mg22462] Defining a function within a module
  • From: Hartmut Wolf <hwolf at debis.com>
  • Date: Thu, 9 Mar 2000 03:24:18 -0500 (EST)
  • Organization: debis Systemhaus
  • References: <200003080721.CAA13108@smc.vnet.net>
  • Sender: owner-wri-mathgroup at wolfram.com

Dear David,

David Park schrieb:
> 
> Dear MathGroup,
> 
> I wish to define and use a function within a module, using an expression passed to
> the module. This is a simpler example, where I simply return the function. If I use
> the mkfun routine, described in Section 2.6.5 of the Mathematica Book, everything
> works. Here x is a global variable without a value, and expr is an expression
> containing x.
> 
> foo1[expr_] :=
>   Module[{mkfun},
>     mkfun[x_, body_] := Function[x, body];
>     mkfun[x, expr]
>     ]
> 
> foo1[x^2]
> Function[x, x^2]
> 
> But, since mkfun simply substitutes x and body into the unevaluated Function, the
> following should also work.
> 
> foo2[expr_] :=
>   Module[{g},
>     g = Hold[Function[x, body]] /. body -> expr;
>     ReleaseHold[g]
>     ]
> 
> foo2[x^2]
> Function[x, x^2]
> 
> It does, but body is a global variable and so the routine will fail if body has a
> value. Therefore, make body internal to the module.
> 
> foo3[expr_] :=
>   Module[{g, body},
>     g = Hold[Function[x, body]] /. body -> expr;
>     ReleaseHold[g]
>     ]
> 
> foo3[x^2]
> Function[x$, x^2]
> 
> This does not work because the variable name has been changed. Why was it changed
> even though it was within a Hold? Why did making body a Module variable rather than a
> global variable cause it to be changed? But in the following routine, we can change
> x$ back to x.
> 
> foo4[expr_] :=
>   Module[{g, body},
>     g = Hold[Function[x, body]] /. body -> expr;
>     ReleaseHold[g] /. x$ -> x
>     ]
> 
> foo4[x^2]
> Function[x, x^2]
> 
> In fact, we don't even need the Hold, since it didn't work anyway.
> 
> foo5[expr_] :=
>   Module[{},
>     Function[x, expr] /. x$ -> x
>     ]
> 
> And here is an even simpler method for obtaining our function.
> 
> foo6[expr_] :=
>   Module[{g},
>     g[x, expr] /. g -> Function
>     ]
> 
> foo6[x^2]
> Function[x, x^2]
> 
> I wish I had a better understanding of when Function does and does not change the
> variable name.
> 


To me it's difficult to see what you want to attain.  Except for structuring 
reasons Module is mainly used to localize variables and to avoid conflicts of 
local code with a (perhaps unknown) global environment.

Now function itself is a scoping construct and also has the attribute HoldAll. 
So, I think, all what you might want to achieve with Module can also be done 
directly with Function. Your examples give no further clue, to me

  Function[x, x^2]

seems to be superiour in any case. If you have

  z = x^2

you may do 

In[]:= Function[x, Evaluate[z]]
Out[]= Function[x, x^2]

If you have

  y = 99

then 

In[]:= Function[y, y^2]
Out[]= Function[y, y^2]

will come out right. If you want to manipulate the expression before 
you can do that, e.g.

In[]:= ((Function[x, #1]) & ) @@ (Hold[y^2] /. HoldPattern[y] -> x)
Out[]= Function[x, x^2]

Also you easily may do some metaprogramming as in

In[]:= (Function[x, x^#] &)[3]
Out[]= Function[x, x^3]


If you want to convert an expression to function -- which can be useful --
this is a (somewhat complicated) example

In[]:= f[___] := 0

In[]:=
(With[{closure = Hold[#1] /. (#1 -> Evaluate @@ #1 & ) /@ 
   Union[Cases[Hold[#1], s_Symbol -> HoldPattern[s], -1, Heads -> False]]}, 

   With[{freevars = Union[Cases[closure, _Symbol?( !NumericQ[#1] & ), -1, 
         Heads -> False]]}, 
     Function[{body}, Function[Evaluate[freevars], body], {HoldFirst}] @@ closure

   ]] &)[Unevaluated[(z^y*f[x, y, z])/E^z]]

Out[]=
Function[{x}, ((x^2)^99*f[x, 99, x^2])/E^x^2]

Here the expression (z^y*f[x, y, z])/E^z is converted to a function of all
those variables which have no definitions or values at the time of this
operation. This here is x, the dependencies of the other symbols on x are 
retained. Yet no evaluation has taken place, as you will have seen from the 
appearance of f in the result.

In the first step all symbols are extracted from the held expression, and 
resubstituted as evaluated into the Held expression (#1 -> Evaluate @@ #1 & ). 
The remaining symbols become the variables of the resulting function. 
(Here !NumericQ excludes E from becoming a variable; this might not always 
be enough, but Infinity, ComplexInfinity or DirectedInfinity[] wouldn't show up 
as variables -- Indefinite does, if not prevented otherwise.)


Now to your question with foo3. The renaming of the variables took place because 
body is a localized variable in Module, and Module tries to rename something in 
function. This is not what you need. If body has a global variable you better 
defend with HoldPattern:

In[34]:= foo3[expr_] := 
  Module[{g}, g = Hold[Function[x, body]] /. HoldPattern[body] -> expr;
    ReleaseHold[g]]

In[35]:= foo3[x^2]
Out[35]= Function[x, x^2]

In[36]:= body
Out[36]= "anything"

Also Hold is not neccessary in this case; body is guarded and if x already has a 
value, it's also guarded within Function, however then replace Rule with RuleDelayed 
and call foo3x with Unevaluated[x^2] :

 
In[49]:= x = 9999;

In[50]:=
foo3x[expr_] := Module[{}, Function[x, body] /. HoldPattern[body] :> expr]

In[51]:= foo3x[Unevaluated[x^2]]
Out[51]= Function[x, x^2]

And as you see again, Module is dispensable.


Kind regards,  Hartmut


  • Prev by Date: Re: Re: Signing with Inequality Constraints
  • Next by Date: publishing with mathematica
  • Previous by thread: Defining a function within a module
  • Next by thread: Re: Defining a function within a module (2)