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
- References:
- Defining a function within a module
- From: "David Park" <djmp@earthlink.net>
- Defining a function within a module