将模块定义为Manipulate表达式与初始化部分中的一部分的任何性能问题?

时间:2011-12-18 06:59:41

标签: wolfram-mathematica

我想询问是否有任何人知道任何问题(表现或其他)如果要定义/放置Manipulate表达式使用的模块,就在Manipulate表达式本身内部,而不是初始化部分,通常在那里完成。

这两种方法都有效,但是从模块直接访问Manipulate动态时语义不一样(相对于它们作为参数传递给模块,实际上这是更好的方法,但我正在尝试现在)

我不知道这些东西是如何实现的,但是我担心如果我把所有模块放在Manipulate表达式中,那么当那里有很多模块时,Manipulate会变慢,因为每次需要刷新表达式时,Mathematica FE将向内核发送一个更大的表达式来重新评估/解析或者正确的术语。

现在刷新的Manipulate表达式现在要大得多,因为模块现在是Manipulate表达式本身的一部分,而不是在初始化部分,即使在每次刷新时都可能没有调用它们,也会发生这种情况。

为了帮助解释这个问题,我在下面做了一个小图来说明我的意思,并排比较两种方法。在下面,我还提出了图表中使用的小代码示例:

enter image description here

表达式方法的代码

Manipulate[
foo[]:=Module[{},
x++
];
ctrl;
foo[],

Button["step",{ctrl++ }],
{{ctrl,0},None},
{{x,0},None},
TrackedSymbols:>{ctrl}

]

模块初始化方法的代码

Manipulate[
 ctrl;
 foo[],

 Button["step", {ctrl++ }],
 {{ctrl, 0}, None},
 {{x, 0}, None},
 TrackedSymbols :> {ctrl},

 Initialization :>
  {
   foo[] := Module[{},
     x++
     ]
   }
 ]

问题是:在modules-inside-manipulate表达方法中是否会出现性能损失?

注意添加:

顺便说一下,在我目前的小型演示中,我没有注意到这两种方法的任何性能差异,但这只是基于观察演示的响应而没有精确的测量。可能是我对Manipulate的初始化部分的理解一直不正确。从帮助中说:

Initialization is an option for Dynamic, DynamicModule, Manipulate, 
and related constructs that specifies an expression to be evaluated when 
the construct is first used or displayed.

看起来我可能认为这与其含义不同。

可能是Manipulate每次都在评估所有模块,作为表达式刷新/更新的一部分吗?

无论哪种方式,如果事实证明两个布局没有性能差异,我会很高兴,因为从现在开始,我将把所有模块放在Manipulate表达式本身,而不是在Initialization部分。

2001年12月19日晚11点 我看了下面发布的Mr. Wizard解决方案。从我看到的,查看Manipulate快照,生成的代码相当于将模块显式放在Manipulate表达式中。下面是一个屏幕截图,显示了每种方法以及由此产生的代码(由Manipulate Function生成,使用快照选项按钮)。我们可以看到它是相同的代码。

但是,巫师先生用来允许函数的技巧被放在Control-> None中,即只写foo而不是foo[]是我不会想到的。我一直认为即使foo[]:=Module[...]没有参数,也必须写foo。 (实际上我从未想过它,我只是自然地在每个函数名的末尾写[],即使没有参数)。感谢分享这个技巧。

enter image description here

2 个答案:

答案 0 :(得分:4)

我认为这必须是特定于应用程序的。您可以在两个示例中的Pause[1];之前插入foo[]:=表达式,以确认在Initialization方法中不进行重新评估,而在另一个方法中进行重新评估。评估表达式需要多长时间的问题是您最有能力回答的问题。为什么不将所有定义放在一个大的Do循环中并将其计时?

此外,虽然我通常不会推荐它,但由于你是在受限制的情况下工作,也许你会打开这种性质的黑客:

Manipulate[
  ctrl; foo[],
  Button["step", {ctrl++}],
  {{ctrl, 0}, None},
  {{x, 0}, None},
  {{foo, Module[{}, x++] &}, None},
  TrackedSymbols :> {ctrl}
]

答案 1 :(得分:1)

回应 2001年12月19日晚11点

正如您在上面自己的屏幕截图中看到的那样,代码实际上是相同的。在上面的示例中,foo的定义是 中的DynamicModule不是的变量列表,它将被重复评估。我相信这正是你想要的功能,不是吗?

您写道:

  

但是,巫师先生用来允许函数的技巧被放在Control-> None中,这就是写foo而不是foo []是我不会想到的。我一直认为必须写foo []:= Module [...]即使foo不参数。 (实际上我从未想过它,我只是自然地在每个函数名的末尾写[],即使没有参数)。感谢分享这个技巧。

不要错过这种机制。 (顺便说一句,我真的很讨厌写Module[{} ...,但是我从你的代码中复制了它。请让我们在将来避免使用它。)

  1. 当您想要执行操作时,使用function[]而不是function表单通常是正确的。虽然很有可能,但它违背了 Mathematica 的性质和语法来触发仅具有函数名称的动作。如果不触发评估,它也很难处理功能。

  2. 您可以使用&而不使用Slot参数来获取上述行为。

  3. 如果我们定义doSomething = Print["Something Done!"] &,我们会用doSomething[]调用它来打印字符串。我们仍然可以使用doSomething编写或传递函数本身,而不会触发评估。