Why is it that not the value of b gets printed in the following example but the symbolname? How can I force the printing of the actual dynamic value of the variable?
a = {1, 2, 3};
DynamicModule[{b},
Print[Dynamic[b]];
{Dynamic[a], Dynamic[b]}
,
Initialization :> (b = Length[a]; a = a + 2)
]
output:
b$107
Out[2]= {{3, 4, 5}, 3}
Edit (after reading your answers/comments):
Consider the more simple example, without Initialization
code (to get around WReach's example):
a = {1, 2, 3};
DynamicModule[{b = Length[a]},
Print[Dynamic[b]];
{Dynamic[a], Dynamic[b]}
]
output:
During evaluation of In[4]:= b$602
Out[5]= {{1, 2, 3}, 3}
Note, that this example does what I want to 开发者_JAVA百科if I use Module
instead of DynamicModule
or leave out Dynamic
from the Print
line. My concerns are:
Why does this second example fail to print the value of b correctly? There is no Initialization, which (according to the help) contains "an expression to evaluate when the DynamicModule is first displayed". Also according to help: "When
DynamicModule
is first evaluated, initial assignments for local variables are made first, and then any setting for theInitialization
option is evaluated."The help should read: "Initialization: an expression to evaluate when the result of
DynamicModule
is first displayed", meaning that aPrint
statement onscreen does not constitute the "result" of theDynamicModule
. If this is correct, then (and only then) I understand why thePrint
statement does not mean that theDynamic
object appears correctly.
I believe this happens because the Dynamic
object b
has not been displayed at the time the Print
statement is called, and therefore the initialization has not been made. As I recall, Dynamic
functionality does not operate until it is actually, visibly displayed.
See Why won't this work? Dynamic in a Select for more information.
In response to your update, my theory is that the Dynamic
statement within Print
in never displayed by the FrontEnd, and therefore it is never actually initialized. That is, it remains a unique placeholder, waiting to be filled by the dynamic value of b
when it is finally displayed.
One may see from the example below that the assignment RHS evaluation takes place before the body Print
, at least by measure of the display order in the FrontEnd. Further, we see that Print
"goes inside" Dynamic
and takes the unique symbol name created by DynamicModule
, and prints that. We can use ToString
to cause Print
to display the entire expression as it is. Likewise, if we extract the symbol name from that string, and convert it to an actual symbol, before printing, we get the expected value that has indeed already been assigned.
alarm := (Print["Initialized!"]; 3)
DynamicModule[{b = alarm},
Print @ ToString @ Dynamic @ b;
Print @ Symbol @ StringTake[ToString@Dynamic@b, {9, -2}];
Print @ Dynamic @ b;
];
Output:
Initialized! Dynamic[b$701] 3 b$701
The crucial behaviour is described under the More Information section of the documentation for DynamicModule:
DynamicModule first gives unique names to local variables in expr, just like Module, then evaluates the resulting expression, and then returns a version of this wrapped in DynamicModule.
The exact sequence of events becomes more apparent if you add a Print
statement to the Initialization
option, thus:
a = {1, 2, 3};
DynamicModule[{b},
Print[Dynamic[b]];
{Dynamic[a], Dynamic[b]}
,
Initialization :> (b = Length[a]; Print["init:", b]; a = a + 2)
]
resulting in three cells:
b$107
Out[7]= {{3, 4, 5}, 3}
init:3
The cell containing b$107
is the result of the Print
inside the DynamicModule
. Then, we get the result cell (tagged Out[7]
here). Finally, we see the third cell output by Print
statement in the Initialization
.
If you inspect the cell expression of the Out[7]
cell, you will find that the localized variable is b$$
. This is different from the variable in the first cell, which is b$107
. This difference is attributable to the "double scoping" described in the DynamicModule
documentation. The b$107
cell contains a Dynamic
box, as can be seen if we assign a value to b$107
.
Update
In response to the updated question...
Returning to the original expression (without the extra Print
in the Initialization
), the exact sequence of events is as follows:
First, the body of the DynamicModule
is evaluated after giving "unique names to local variables [...] just like Module". That is, this expression is evaluated:
Print[Dynamic[b$107]]; {Dynamic[a], Dynamic[b$107]}
The result of this expression is the list {Dynamic[a], Dynamic[b$107]}
. As a side-effect, a dynamic cell containing b$107
is created but that cell is now removed from further consideration as it is not part of the result of the evaluation. Now, "a version of [{Dynamic[a], Dynamic[b$107]}
] is wrapped in DynamicModule" and returned. This is evaluated and implicitly printed to produce an output cell expression like this:
Cell[BoxData[
DynamicModuleBox[{$CellContext`b$$ = 3},
RowBox[{"{",
RowBox[{
DynamicBox[ToBoxes[$CellContext`a, StandardForm],
ImageSizeCache->{57., {2., 8.}}], ",",
DynamicBox[ToBoxes[$CellContext`b$$, StandardForm],
ImageSizeCache->{7., {0., 8.}}]}], "}"}],
DynamicModuleValues:>{},
Initialization:>($CellContext`b$$ =
Length[$CellContext`a]; $CellContext`a = $CellContext`a + 2)]], "Output"]
Note particularly that b$107
is renamed to $CellContext`b$$
as a function of DynamicModule
symbol localization. The Initialization
expression is now evaluated as the box is displayed and visible.
The key point is that the printed cell containing b$107
is not coupled in any way to the final DynamicModule
cell.
精彩评论