If you want to be really careful, you should properly localize the variables and add syntax checking to your function. Here is a way to do this:
ClearAll[newtonsMethod]
SetAttributes[newtonsMethod, HoldAll];
SyntaxInformation[
newtonsMethod] = {"LocalVariables" -> {"FindRoot", {2, 2}},
"ArgumentsPattern" -> {_, _, OptionsPattern[]}};
newtonsMethod[expr_, {x_, x0_, n_}] :=
Module[{f, xSymbol, xLocal},
xSymbol = Unevaluated[x] /. x1_ :> HoldPattern[x1];
f[xLocal_] := Unevaluated[expr] /. xSymbol :> xLocal;
Nest[# - f[#]/f'[#] &, x0, n]]
newtonsMethod[x^2 - 2, {x, 1., 10}]
1.41421
The feature I added in this answer is that the syntax is just like it is in FindRoot
, including the fact that x
is treated as a local variable even if it has a global value. You can try this by setting e.g. x = 0
and then calling newtonsMethod
again. Without the use of Unevaluated
and HoldPattern
to replace the global variable in the expression, you'd have to manually clear x
before calling the function with the expression x^2 - 2
.
Since FindRoot
returns a replacement rule of the form {x->1.41421}
, it can't be immune against global assignments to x
: With a global setting x = 0
, you would get
FindRoot[x^2 - 2, {x, 1}]
{0 -> 1.41421}
Here, the internal workings of FindRoot
do in fact localize x
so that the correct solution value is found (1.41421
), but then x
is replaced by 0
because the output {x -> 1.41421}
is evaluated.