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