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