在DynamicModule中打印动态变量

时间:2011-10-11 18:41:13

标签: dynamic wolfram-mathematica

为什么在以下示例中 b 的值不是打印而是符号名?如何强制打印变量的实际动态值?

a = {1, 2, 3};

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

输出:

b$107

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

修改(阅读您的回答/评论后):

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

a = {1, 2, 3};

DynamicModule[{b = Length[a]},
 Print[Dynamic[b]];
 {Dynamic[a], Dynamic[b]}
 ]

输出:

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

Out[5]= {{1, 2, 3}, 3}

请注意,如果我使用Module代替DynamicModule或从Dynamic行中遗漏Print,则此示例会执行我想要的操作。我担心的是:

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

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

2 个答案:

答案 0 :(得分:6)

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

有关详细信息,请参阅Why won't this work? Dynamic in a Select


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

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

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

DynamicModule[{b = alarm},
  Print @ ToString @ Dynamic @ b;
  Print @ Symbol @ StringTake[ToString@Dynamic@b, {9, -2}];
  Print @ Dynamic @ b;
];

输出:

Initialized!

Dynamic[b$701]

3

b$701 

答案 1 :(得分:3)

关键行为在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)
 ]

产生三个细胞:

        b$107

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

        init:3

包含b$107的单元格是PrintDynamicModule的结果。然后,我们得到结果单元格(此处标记为Out[7])。最后,我们在Print中通过Initialization语句看到第三个单元格输出。

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

<强>更新

回应更新后的问题......

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

首先,在给出“模块”之类的“局部变量[...]的唯一名称”之后,对DynamicModule的主体进行评估。也就是说,评估此表达式:

Print[Dynamic[b$107]]; {Dynamic[a], Dynamic[b$107]}

此表达式的结果是列表{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"]

请特别注意b$107作为$CellContext`b$$符号本地化的函数重命名为DynamicModule。现在评估Initialization表达式,因为该框显示并可见。

关键是包含b$107的打印单元格没有以任何方式耦合到最终的DynamicModule单元格。