在DynamicModule中打印动态变量

Ist*_*har 6 wolfram-mathematica dynamic

为什么不是值b在下面的例子,但符号名称?如何强制打印变量的实际动态值?

a = {1, 2, 3};

DynamicModule[{b},
 Print[Dynamic[b]];
 {Dynamic[a], Dynamic[b]}
 ,
 Initialization :> (b = Length[a]; a = a + 2)
 ]
Run Code Online (Sandbox Code Playgroud)

输出:

b$107

Out[2]= {{3, 4, 5}, 3}
Run Code Online (Sandbox Code Playgroud)

编辑(阅读你的答案/评论后):

考虑一个更简单的例子,没有Initialization代码(绕过WReach的例子):

a = {1, 2, 3};

DynamicModule[{b = Length[a]},
 Print[Dynamic[b]];
 {Dynamic[a], Dynamic[b]}
 ]
Run Code Online (Sandbox Code Playgroud)

输出:

During evaluation of In[4]:= b$602

Out[5]= {{1, 2, 3}, 3}
Run Code Online (Sandbox Code Playgroud)

请注意,如果我使用Module而不是DynamicModuleDynamicPrint行中省略,此示例执行我想要的操作.我担心的是:

  1. 为什么第二个例子无法正确打印b的值?没有初始化,它(根据帮助)包含"一个表达式,用于评估何时首次显示DynamicModule".另外根据帮助:" DynamicModule首次评估时,首先进行局部变量的初始分配,然后Initialization评估该选项的任何设置."

  2. 帮助应该是:"初始化:一个表达式,用于评估何时首次显示结果 DynamicModule ",这意味着Print屏幕上的语句不构成"结果" DynamicModule.如果这是正确的,那么(并且只有那时)我明白为什么Print声明并不意味着Dynamic对象正确显示.

Mr.*_*ard 6

我相信这是因为在Dynamic调用语句b时没有显示对象Print,因此尚未进行初始化.我记得,Dynamic功能在实际可见之前不会运行.

看看为什么这不起作用?动态选择以获取更多信息.


为了响应您的更新,我的理论是FrontEnd 中的Dynamic语句Print从未显示过,因此它实际上从未被初始化.也就是说,它仍然是一个独特的占位符,等待b最终显示时的动态值.

从下面的例子可以看出,分配RHS评估发生在身体之前Print,至少通过测量FrontEnd中的显示顺序.此外,我们看到Print"进入内部" Dynamic并获取由其创建的唯一符号名称DynamicModule,并打印出来.我们可以使用ToStringPrint来显示整个表达式.同样,如果我们从该字符串中提取符号名称,并在打印之前将其转换为实际符号,我们将获得确实已经分配的预期值.

alarm := (Print["Initialized!"]; 3)

DynamicModule[{b = alarm},
  Print @ ToString @ Dynamic @ b;
  Print @ Symbol @ StringTake[ToString@Dynamic@b, {9, -2}];
  Print @ Dynamic @ b;
];
Run Code Online (Sandbox Code Playgroud)

输出:

Initialized!

Dynamic[b$701]

3

b$701 


WRe*_*ach 4

DynamicModule文档的更多信息部分描述了关键行为:

DynamicModule首先为expr中的局部变量提供唯一的名称,就像Module一样,然后计算结果表达式,然后返回包装在DynamicModule中的版本。

Print如果您向选项添加一条语句,事件的确切顺序将变得更加明显Initialization,因此:

a = {1, 2, 3};

DynamicModule[{b},
 Print[Dynamic[b]];
 {Dynamic[a], Dynamic[b]}
 ,
 Initialization :> (b = Length[a]; Print["init:", b]; a = a + 2)
 ]
Run Code Online (Sandbox Code Playgroud)

产生三个单元格:

        b$107

Out[7]= {{3, 4, 5}, 3}

        init:3
Run Code Online (Sandbox Code Playgroud)

包含的单元格是内部b$107的结果。然后,我们得到结果单元格(在此处标记)。最后,我们看到.txt 文件中by 语句的第三个单元格输出。PrintDynamicModuleOut[7]PrintInitialization

如果你检查单元格的单元格表达式Out[7],你会发现局部变量是b$$。这与第一个单元格中的变量 不同b$107。这种差异可归因于DynamicModule文档中描述的“双重范围”。该b$107单元格包含一个Dynamic框,如果我们为 赋值就可以看到b$107

更新

回答更新的问题...

返回到原始表达式(没有Print中的额外内容Initialization),事件的确切顺序如下:

DynamicModule首先,在“为局部变量提供唯一的名称[...]就像模块一样”之后,对主体进行评估。也就是说,该表达式的计算结果为:

Print[Dynamic[b$107]]; {Dynamic[a], Dynamic[b$107]}
Run Code Online (Sandbox Code Playgroud)

该表达式的结果是列表{Dynamic[a], Dynamic[b$107]}。作为副作用,b$107创建了包含的动态单元格,但该单元格现在已从进一步考虑中删除,因为它不是评估结果的一部分。现在,“[ {Dynamic[a], Dynamic[b$107]}] 的一个版本被包装在DynamicModule中”并返回。对此进行评估并隐式打印以生成如下输出单元表达式:

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"]
Run Code Online (Sandbox Code Playgroud)

特别注意,它b$107被重命名$CellContext`b$$为符号本地化的函数DynamicModuleInitialization现在,当框显示且可见时,将计算表达式。

关键点是所包含的印刷单元b$107不以任何方式耦合到最终DynamicModule单元。