Wolfram mathematica 与初始化部分相比,将模块定义为操纵表达式的一部分有任何性能问题吗?

Wolfram mathematica 与初始化部分相比,将模块定义为操纵表达式的一部分有任何性能问题吗?,wolfram-mathematica,Wolfram Mathematica,我想问一下,如果要定义/放置操纵表达式使用的模块,是否有人知道任何问题(性能或其他方面),就在操纵表达式本身内部,而不是在初始化部分,通常在初始化部分完成 这两种方法都可以工作,但在直接访问模块以操纵动态时,语义并不相同(而不是将它们作为参数传递给模块,这实际上是更好的方法,但我现在正在尝试) 我不知道这些东西是如何实现的,但是我担心如果我把所有的模块都放在操纵表达式中,那么当有很多模块时操纵会变慢,因为每次都需要刷新表达式,Mathematica FE将向内核发送一个现在大得多的表达式,以重新

我想问一下,如果要定义/放置操纵表达式使用的模块,是否有人知道任何问题(性能或其他方面),就在操纵表达式本身内部,而不是在初始化部分,通常在初始化部分完成

这两种方法都可以工作,但在直接访问模块以操纵动态时,语义并不相同(而不是将它们作为参数传递给模块,这实际上是更好的方法,但我现在正在尝试)

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

现在刷新的操纵表达式现在要大得多,因为模块现在是操纵表达式本身的一部分,而不是在初始化部分,即使在每次刷新时可能不会调用其中的一些模块,也会发生这种情况

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

表达式方法部分的代码

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++
     ]
   }
 ]
初始化方法中的模块代码

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++
     ]
   }
 ]
问题是:操纵表达式方法中的模块是否会受到性能影响

添加注释:

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

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.
看起来我对它的理解可能与它的含义不同

作为表达式刷新/更新的一部分,是否每次都要计算所有模块

无论哪种方式,如果两种布局的性能没有差异,我都会很高兴,从现在起,我将把所有模块放在操纵表达式本身中,而不是放在初始化部分

新增2001年12月19日晚上11时 我查看了下面发布的向导先生解决方案。从我所看到的,查看操纵快照,生成的代码相当于显式地将模块放入操纵表达式中。下面是一个屏幕截图,显示了这两种方法,以及每个布局的结果代码(通过操纵函数,通过使用快照选项按钮生成)。我们可以看到它是相同的代码

但是Mr Wizard允许将函数放入控件->无,即只编写
foo
而不是
foo[]
的技巧是我没有想到的。我一直认为必须编写
foo[]:=Module[…]
,即使
foo
不带参数。(实际上我从来没有想过,我只是在每个函数名的末尾自然地写[],即使不带参数)。谢谢分享这个技巧


我认为这必须是特定于应用程序的。您可以插入
暂停[1]foo[]之前的code>表达式:=
,以确认在
初始化
方法中不会进行重新评估,而在另一个示例中会进行重新评估。计算表达式所需时间的问题是您最适合回答的问题。为什么不把所有的定义放在一个大的
Do
循环中并计时呢

另外,虽然我通常不会推荐它,但由于您是在受限条件下工作的,也许您正在打开一个类似于此的黑客程序:

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

2001年12月19日晚上11点回复您添加的

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

你写道:

但是Mr Wizard使用的技巧是允许将函数放入控件->无,即只编写foo而不是foo[],这是我没有想到的。我一直认为,即使foo不带参数,也必须编写foo[]:=Module[…]。(实际上我从来没有想过,我只是在每个函数名的末尾自然地写[],即使不带参数)。谢谢分享这个技巧

不要错过它的工作机制。(顺便说一句,我真的很讨厌编写
模块[{}…
,但我是从您的代码中复制的。请让我们以后避免这种构造。)

  • 通常使用
    函数[]形式是正确的
    而不是
    函数
    当你想执行一个动作时。虽然很有可能,但触发一个动作时只使用函数名是违反Mathematica的性质和语法的。这也使得在不触发求值的情况下处理函数本身变得困难

  • 通过使用不带
    插槽
    参数的
    &
    可以获得上述行为


  • 如果我们定义
    doSomething=Print[“Something!”]&
    我们就用
    doSomething[]来调用它
    打印字符串。我们仍然可以使用
    doSomething
    编写或传递函数本身,而不触发求值。

    我觉得性能是一个错误的问题,因为我相信您完全有能力自己找到答案。至于本地化
    x
    :为什么不包装
    动态模块
    Module
    在y附近