Re: Replace in Modules
- To: mathgroup at smc.vnet.net
- Subject: [mg81263] Re: Replace in Modules
- From: Jean-Marc Gulliet <jeanmarc.gulliet at gmail.com>
- Date: Tue, 18 Sep 2007 00:35:13 -0400 (EDT)
- Organization: The Open University, Milton Keynes, UK
- References: <fcg3t2$rcr$1@smc.vnet.net>
Joerg Schaber wrote: > why doesn't the following give me the square root? > > f[x_] := Module[{a, y},y = x;Return[FindRoot[y == a^2, {a, 1}]]] > > f[z] /. {z -> 2} > > where as > > f[x_] := Module[{a},Return[FindRoot[x == a^2, {a, 1}]]] > > f[z] /. {z -> 2} > > works fine? Well, I would not say that the second expression is working fine since several error messages are displayed during the evaluation process and the answer is a rule (nothing wrong here) that contains the name of a local symbol (something is terribly wrong here). Of course, if you disregards these two major issues and if you do not need to use the result anyway (otherwise you must add some additional code that is going to convert the local name to a global one that can be use in subsequent evaluation), the function can be deemed as successful in its attempt to compute sqrt(2). In[1]:= f[x_] := Module[{a}, Return[FindRoot[x == a^2, {a, 1}]]] f[z] /. {z -> 2} During evaluation of In[1]:= FindRoot::nlnum: The function value \ {-1.+z} is not a list of numbers with dimensions {1} at {a$65} = \ {1.}. >> During evaluation of In[1]:= FindRoot::nlnum: The function value \ {-1.+z} is not a list of numbers with dimensions {1} at {a$65} = \ {1.}. >> During evaluation of In[1]:= FindRoot::nlnum: The function value \ {-1.+z} is not a list of numbers with dimensions {1} at {a$65} = \ {1.}. >> During evaluation of In[1]:= General::stop: Further output of \ FindRoot::nlnum will be suppressed during this calculation. >> Out[2]= {a$65 -> 1.41421} (Note that *Return* is not needed: the value of the last expression to be evaluated is returned.) Having said that, what explains the differences in behavior is /not/ *Module* but operator _precedences_ (or priorities if you want). Let see how the following expression is evaluated When Mathematica evaluates the expression f[z] /. z -> 2, it starts from the left, that is it evaluates first f[z], only then it applies the transformation rule to the result returned by the evaluation of f[z]. So, using the first definition of f[x] and assuming that z has no global value, we have the following sequence: x is replace by z as the formal name of the argument, y takes the value of z that is 'z' since at this stage z has no value, then FindRoot is called with some argument which does not have any numeric value (the infamous -1 + z in the error messages) so it complains and returns unevaluated. This unevaluated form of FindRoot is passed on to the replacement rule z -> 2 which has nothing to replace since no z are present in the expression; therefore the unevaluated FindRoot is what is returned as final answer. Now, if z has a global value before evaluating the expression f[z] /. z -> 2, as you can see below, none of them work as expected (though the results are expected from Mathematica point of view). In[6]:= z = 5; f[x_] := Module[{a, y}, y = x; Return[FindRoot[y == a^2, {a, 1}]]] f[z] /. {z -> 2} Out[8]= {a$181 -> 2.23607} In[9]:= z = 9; f[x_] := Module[{a}, Return[FindRoot[x == a^2, {a, 1}]]] f[z] /. {z -> 2} Out[11]= {a$187 -> 3.} The expected numerical value can be obtained by putting the replacement rule inside the square brackets (which is equivalent to evaluating f[2], indeed). In[12]:= z = 5; f[x_] := Module[{a, y}, y = x; Return[FindRoot[y == a^2, {a, 1}]]] f[z /. z -> 2] Out[14]= {a$193 -> 1.41421} In[15]:= z = 9; f[x_] := Module[{a}, Return[FindRoot[x == a^2, {a, 1}]]] f[z /. z -> 2] Out[17]= {a$199 -> 1.41421} Finally, a correct way to code your function could be f[(z_)?NumericQ] := Module[{a}, a /. FindRoot[z == a^2, {a, 1}]] since you do note return any spurious local name into the global context. Regards, -- Jean-Marc