Explanation of the behavior
First, let me dispense with the OP's second example. I assume RandomReal[{-1, 1}]
is treated as not depending on any symbol (except possibly RandomReal
, although I would not be surprised if Protected
symbols were excluded from dynamic tracking). So unlike Clock
, RandomReal
will not cause an update merely because it will probably return a different answer each time. For this reason, the OP's second example is unproblematic.
This baffled me because at first I expected the first of the OP's examples to update continually. For instance, this seemingly unimportant modification does update continually:
Dynamic[
th; (* a1 *)
th = RandomReal[{-1, 1}]; (* a2 *)
th (* a3 *)
]
The way I explain it to myself is this. I will compare it with the OP's first example, with the lines of code identified for convenient reference.
Dynamic[
th = RandomReal[{-1, 1}]; (* b1 *)
th (* b2 *)
]
Determining when an update is triggered comes down (it seems) to whether an assignment would alter the result of executing the code again. (Keep in mind that I'm assuming RandomReal
is treated as if it gave the same value for the same input.) In my example, line a2
changes th
, which means the previous line a1
would have a different result. This triggers an update. In the OP's example, the assignment in line b1
has no such effect. The symbol th
appears only after the assignment, so no update is necessary.
In the interest of efficiency, there may be a limit to how precisely Mathematica can determine the dependency of a code segment on a symbol. In such cases, I would expect Mathematica to be conservative and assume that a update should be done.
This analyis has a bearing on the main question, which for me is, Why does wrapping the first of the OP's examples inside a DynamicModule
makes a difference?
Strictly speaking it is not merely DynamicModule
. The following does not update continually:
DynamicModule[{},
Dynamic[
th = RandomReal[{-1, 1}];
th
]]
It has to do with th
being a DynamicModule
variable. As such, it is owned by the Front End. If we look at the cell expressions of the two examples, we will see something important:
(* No DynamicModule example (OP's 1st) *)
Cell[BoxData[
DynamicBox[ToBoxes[$CellContext`th = RandomReal[{-1, 1}]; $CellContext`th, StandardForm],
ImageSizeCache->{95., {1., 13.}}]], "Output",
CellChangeTimes->{3.603873092328042*^9}]
(* DynamicModule example (OP's 3rd) *)
Cell[BoxData[
DynamicModuleBox[{$CellContext`th$$ = -0.014046062447770069`},
DynamicBox[
ToBoxes[$CellContext`th$$ = RandomReal[{-1, 1}]; $CellContext`th$$,
StandardForm],
ImageSizeCache->{118., {1., 13.}}],
DynamicModuleValues:>{}]], "Output",
CellChangeTimes->{3.6038735203232813`*^9}]
Note that the current value of th
is stored in the DynamicModule
expression maintained by the Front End. The initialization (in the second line) is like line a1
above; it is evaluated first. At first, the line is simply
DynamicModuleBox[{$CellContext`th$$},
in which case it is just like the line a1
. The value of th
will be changed when the Front End sends the body of the DynamicModule
to Kernel for evaluation. This change will trigger another update, just as in my first "a
" example above. That's why, I think, that the OP's third example updates continually.
Fix of the OP's last example
Personally, I would probably use esprit's TrackedSymbols
solution, perhaps with Refresh
. For the sake of offering a complete answer, here's another way:
DynamicModule[{th, ft, rr, f, m, c, x, res, updateRR},
Column[{
Row[{Slider[Dynamic[rr, updateRR], {0, 10}], " ran amp = ", Dynamic[rr]}],
Dynamic[{m, c} /. res],
Dynamic[
ListPlot[Abs[ft[[1 ;; 200]]], PlotRange -> All, ImageSize -> 5 * 72,
Epilog -> {Line[{{1, c}, {200, m 200 + c}} /. res]}]
]
}],
Initialization :> (
rr = 1;
f = 0.2345;
updateRR = (rr = #;
th = Table[Cos[2 π f (n - 1)] + RandomReal[{-rr, rr}], {n, 400}];
ft = Fourier[th, FourierParameters -> {-1, -1}];
res = FindFit[Abs[ft[[1 ;; 200]]], m x + c, {c, m}, x]) &;
updateRR[rr])
]
The trick is to update the symbols that depend only on rr
at the time rr
is updated, using the second argument of Dynamic
.
DynamicModule[{th}, Dynamic[th = RandomReal[{-1, 1}]; th, TrackedSymbols -> {}]]
$\endgroup$