Intro
I'll try to give some quick principals to guide one's thinking about scoping and Dynamic[]
. Dynamic[]
is complicated, and this answer will not explain everything. The Quiz at the end probably reveals this. Perhaps the OP doesn't even need Dynamic[]
, as has been suggested. Perhaps one's actual use-case does need Dynamic[]
. In any case, here is the basic beginning advice: The variables inside Dynamic[]
should be global on purpose or inside a DynamicModule[]
containing the Dynamic[]
. For instance, I use Dynamic[]
on purpose to monitor the progress of global variables in a time-consuming computation.
Some principals of scoping
Dynamic[code]
lives "forever," until the output is deleted from the notebook. It outlives kernel sessions. It outlives front end sessions. It is reevaluated when notebooks are reopened. If it is to work "forever," then the dependencies of code
have to live "forever." DynamicModule[]
is typically the way one makes this happen (see further down).
Block[{vars}, code]
hijacks the global variables in vars
, saves their values, clears (and optionally initializes) them for the execution of code
. This lasts until Block[]
has finished evaluating. Any changes to the values of vars
happen to the global variables. (This is useful for temporarily resetting system parameters like $RecursionLimit
or $MinPrecision
etc.) Any external Dynamic[]
that depends on vars
will be updated with the new values. When Block[]
is finished and the old values are restored, Dynamic[]
will again reevaluate its code.
Module[{vars}, code]
creates unique global symbols based on the symbol names of vars
. They have the attribute Temporary
, which means that if the symbols do not leak out of the module, they will be removed after Module[]
is done. Module[]
variables could leak out like this: Module[{x = 1}, Dynamic[x]]
. When the kernel session is over, the module variable x
will be removed. and Dynamic[x]
will display the unique symbol name for x
that the Module[]
created. The name will vary by session; see $ModuleNumber
. Module[]
is somewhat similar to Block[]
, but its creating new symbols for the vars
is important. It explains why the OP sees different behavior for Module[]
. It means that every call to Module[]
creates a new and distinct symbol for x
; whereas Block[]
reuses the same global x
each time, and other any other process may use the same x
, too.
DynamicModule[{vars}, code]
lives "forever," until the output is deleted from the notebook. It stores values for vars
from session to session (as text in the notebook). The values will be in the notebook for Dynamic[]
to use when the notebook is reopened (provided it is inside a DynamicModule[]
and displayed in the output cell). These variables are "localized" each time the dynamic output is instantiated. Instantiation includes when you copy a DynamicModule[]
output and paste in a notebook (same or different one, it does not matter). The vars
are localized in a similar way to Module[]
: Unique symbols names are created for each instance. They are recreated, possibly with different names, when the notebook is reopened. The new names are substituted for the vars
in the instantiation process.
[*Re "global": Arguably every symbol in Mathematica is global. There is the "Global`"
context, which is for the user-global symbols. But all symbols are accessible, and they are writable if not Protected
or Locked
. By "global" above, I mean principally the symbols in the "Global`"
and "System`"
contexts.]
Block[{x = 1}, code]
Block[{x = 1}, code]
expresses an intention of temporarily resetting the global value of x
while code
is executing. The temporary aspect suggests that Block[{x = 1}, Dynamic[x]]
is a mistake, as it expresses simultaneously that x
should temporarily be changed as well as permanently be part of the evaluation notebook. One might imagine reasons for doing this on purpose, and therefore, it is not treated as an error. Mathematica will run the code. You just get red highlighting, which you could change in Preferences, if it annoys you.
Output from DynamicModule[{x = 1}, code]
DynamicModule[{x = 1},
Print@x;
Print@Dynamic@x;
Dynamic@x]
(* 1 *)
(* x$20686492 $*)
(* 1 *)
The Print[e]
cells contain their output outside any DynamicModule[]
. In the first output line, the value of x
is printed. In the second, because Dynamic[]
holds x
, we get a module variable with a module number tacked on (invisibly wrapped in Dynamic[]
. The third output is a DynamicModule[]
:
% // InputForm
(* DynamicModule[{x = 1}, Dynamic[x], DynamicModuleValues :> {}] *)
Note that it is note the same module. The body code
, a CompoundExpression[]
, has been evaluated in a module setting, and what we get is the DynamicModule[]
wrapped around the value of the body.
Quiz
What variable does the Slider[]
control?:
A.
DynamicModule[{x = 1},
Print@x;
Print@Dynamic@x;
Print@Slider@Dynamic@x;
{Dynamic@x, Dynamic@Hold@x}]
B.
DynamicModule[{x = 1},
Print@x;
Print@Dynamic@x;
{Dynamic@x, Dynamic@Hold@x, Slider[Dynamic@x]}]
Bonus: Why is the x
different in Print@Dynamic@x
and Dynamic@Hold@x
?