On the off chance that an explanation would be appreciated, one that explains how to think about definitions and would help one avoid making such mistakes, instead of just some working code, I offer the following.
First, gratuitous advice: Why should I avoid the For loop in Mathematica?
Using Do[body, {j, n-1}]
instead of For[j = 1, j < n, j++, body]
won't solve any of the problems in the OP (hence, "gratuitous"), but the advantages are discussed in the linked Q&A. When body
effectively has the form y = G[y]
, then Nest[]
is an appropriate tool to use instead of For[]
or Do[]
(see @flinty's answer).
1A.
The first error is explained by this:
If I execute the OP's first-example code, I don't get any errors on a clean start. The errors are due to a lingering definition, probably f[x_] := Sin[x]
, but possibly f = Sin
. The following probably should be the advice in the link above (but it's not):
- Start your definition of
f
with ClearAll[f]
.
Add the line ClearAll[f];
to the first example and the errors disappear.
1B.
Even with the ClearAll
fix, the first example contains another bug not exhibited in the example code:
f[2][x]
$RecursionLimit::reclim2: Recursion depth of 1024 exceeded during evaluation of f[j][x].
(* Hold[\[Integral]f[j][x] \[DifferentialD]x] *)
There are various ways to look at the issues. They concerned the order of evaluation, including held arguments, and the following:
You can see the effect of Set
or SetDelayed
with ? f
, which shows the effect is to define SubValues
for f
. (in the first example you would need SubValues[f]
, which you can read about in the third link in the list.
ClearAll[f, j];
n = 2;
f[1][x_] := Sin[x];
For[j = 1, j < n, j++, f[j + 1][x_] := Integrate[f[j][x], x]];
SubValues[f]
(*
{HoldPattern[f[1][x_]] :> Sin[x],
HoldPattern[f[2][x_]] :> Integrate[f[j][x], x]}
*)
Note the effect of the definition in the For
loop. Because the right-hand side is "held" (not evaluated), the literal f[j]
appears in replace rule in SubValues
. At this point, j
has a value 2
after the For
loop. So f[2][x]
evaluates as follows:
f[2][x] --> apply the SubValue for f[2][x_]
Integrate[f[j][x], x] --> Integrate now evaluates f[j][x]
f[j][x] --> j=2, so...
f[2][x] --> apply the SubValue for f[2][x_]
Integrate[f[j][x], x], x] --> Integrate now evaluates f[j][x]
f[j][x] --> j=2, so...
f[2][x] --> ... ad infinitum or until $RecursionLimit is reached
You could clear j
or set j = 3
or to another value to see how it affects the result.
i)
One workaround is to use Set
instead of SetDelayed
in the For
loop:
f[j + 1][x_] = Integrate[f[j][x], x]
With Set
, the RHS is evaluated before the definition is made. Then the SubValues
become the following and contain no recursive reference to f
:
SubValues[f]
(*
{HoldPattern[f[1][x_]] :> Sin[x],
HoldPattern[f[2][x_]] :> -Cos[x]}
*)
ii)
Another workaround is to inject the value of j
into the definition using With
:
With[{j = j}, f[j + 1][x_] := Integrate[f[j][x], x]]
Now the SubValues
are the following:
SubValues[f]
(*
{HoldPattern[f[1][x_]] :> Sin[x],
HoldPattern[f[2][x$_]] :> Integrate[f[1][x$], x$]}
*)
Note that the reference to f
in the definition of f[2]
is to f[1]
, so we won't get an infinite recursion.
2.
The issue here is similar to 1B.
In this case you can see the effect of SetDelayed
with ? f
or with DownValues[f]
):
ClearAll[f, j];
n = 2;
f[x_] := Sin[x];
For[j = 1, j < n, j++, f[x_] := Integrate[f[x], x]]
DownValues[f]
(*
HoldPattern[f[x_]] :> Integrate[f[x], x]}
*)
Because the right-hand side of SetDelayed
is "held" (not evaluated), the expression f[x]
appears in replacement rule in DownValues
. Thus we get infinite recursion. The first workaround in 1B, using Set
, can be applied here:
ClearAll[f, j, x];
n = 2;
f[x_] := Sin[x];
For[j = 1, j < n, j++, f[x_] = Integrate[f[x], x]]
DownValues[f]
(* {HoldPattern[f[x_]] :> -Cos[x]} *)
Of course, now the body
has the form y = G[y]
, and thus Nest[]
is an appropriate tool to use instead of For[]
.