Wolfram mathematica Mathematica中有没有简单的机制来创建具有持久状态的模块?
在C语言中,当我在函数中定义局部变量时,如果我想在调用之间保存局部变量值,我通常会在变量旁边添加static这个词 这给了我变量名的局部范围保护,但同时,变量值是持久的。模拟一个保存自己私有状态的简单对象非常有用 是否可以在Mathematica中使用Wolfram mathematica Mathematica中有没有简单的机制来创建具有持久状态的模块?,wolfram-mathematica,Wolfram Mathematica,在C语言中,当我在函数中定义局部变量时,如果我想在调用之间保存局部变量值,我通常会在变量旁边添加static这个词 这给了我变量名的局部范围保护,但同时,变量值是持久的。模拟一个保存自己私有状态的简单对象非常有用 是否可以在Mathematica中使用Module[]?或者动态模块[] (我们知道默认情况下,Module[]不会保存局部变量状态,但是使用DynamicModule[]?)怎么样 不使用包。使用它的上下文位于操纵[]中 任何模块[]都不能在外部操作。因此,一切都必须是这样的: M
Module[]
?或者动态模块[]
(我们知道默认情况下,Module[]
不会保存局部变量状态,但是使用DynamicModule[]
?)怎么样
不使用包。使用它的上下文位于操纵[]
中
任何模块[]
都不能在外部操作。因此,一切都必须是这样的:
Manipulate[
foo[]:=Module[{a,b,c},....];
boo[]:=Module[{a,b,c},....];
... foo[] ..
... boo[]...
..,
control_variables...,
Initialization:>
(
.... global area....
)
]
Manipulate[
ctrl;
Grid[{
{"processA result=", processA[]},
{"processB result=", processB[]}
}],
Button["step", ctrl++],
{{ctrl, 0}, None},
{{processA, Module[{total = 0}, total++] &}, None},
{{processB, Module[{total = 0}, total++] &}, None},
TrackedSymbols :> {ctrl}
]
我试着用DynamicModule
代替上面的Module[]
来实现这一点,但是DynamicModules
不能作为函数调用吗?我不知道该怎么做
问题是:是否有可能让函数在调用之间记住其局部变量的值,例如使用带有局部静态变量的C时就可以做到这一点?
当然,不能用全局变量保存状态,这就是我问这个问题的全部目的。我希望模块状态保存在只属于该模块的上下文中
我不是在要求任何高级OO仿真。只是想将模块使用的几个局部变量保存在属于该模块的名称范围中,而不是保存在全局上下文中,并使它们在对模块的调用之间保持不变
更新
为了清楚起见,这里有一个非常基本的C示例
#include <stdio.h>
void my_add(void)
{
static int total = 0;
total = total + 1;
printf("current total %d\n",total);
}
int main()
{
int i;
for(i = 1; i<=3; i++)
my_add();
return 0;
}
$ gcc ex.c
$ ./a.exe
current total 1
current total 2
current total 3
$
每次我按下按钮,总数仍然是1。它不保存最后一个值
上午9:13更新
对于内部的环形解决方案:
下面是一个测试:
Manipulate[
n;
Grid[{
{"module A result=", aResult}
}],
Button["press to update process A", {n++; aResult = processA[n]}],
{{n, 0}, None},
{{aResult, {}}, None},
TrackedSymbols :> {n},
Initialization :>
(
Module[{total = 0},
processA[n_] :=
(
total = total + 1;
{n, total}
)
]
)
]
就其本身而言,这似乎是可行的。但当我复制了一个单元格,并将其粘贴到新的单元格时。然后运行第二个操纵,更新那里的总数,然后返回到第一个操纵,更新那里的总数,我看到它正在使用第二个操纵中更新的总数。因此它是全球性的
这在演示中是不允许的。快照已拍摄,无法共享状态(演示中不允许使用全局变量。初始化部分不得包含全局共享数据。但可以包含仅通过操纵表达式中的参数调用的函数,没有问题
上午9:40更新
回复Mr向导下面的第二个示例,关于他显示的模式,如下所示:
Manipulate[
{x, myAdd[]},
{x, 1, 10},
{{total, 0}, None},
{{myAdd, (total += 1; total) &}, None}
]
问题是,名称total
不能由两个不同的函数使用。total
的名称空间跨越整个函数。我希望使用这种模式:
Manipulate[
foo[]:=Module[{a,b,c},....];
boo[]:=Module[{a,b,c},....];
... foo[] ..
... boo[]...
..,
control_variables...,
Initialization:>
(
.... global area....
)
]
Manipulate[
ctrl;
Grid[{
{"processA result=", processA[]},
{"processB result=", processB[]}
}],
Button["step", ctrl++],
{{ctrl, 0}, None},
{{processA, Module[{total = 0}, total++] &}, None},
{{processB, Module[{total = 0}, total++] &}, None},
TrackedSymbols :> {ctrl}
]
你看,在上面,processA有它自己的本地总数,processB也有。相同的本地名称。上面的方法不起作用。如果我用下面的方法替换上面的方法使其“起作用”
Manipulate[
ctrl;
Grid[{
{"processA result=", processA[]},
{"processB result=", processB[]}
}],
Button["step", ctrl++],
{{ctrl, 0}, None},
{{total, 0}, None},
{{processA, Module[{}, total++] &}, None},
{{processB, Module[{}, total++] &}, None},
TrackedSymbols :> {ctrl}
]
然后processA和processB现在共享同一个总变量,这就克服了让它们都在单独的名称空间中,并且在调用的整个生命周期中都是持久的这一点
上午10点更新
哎呀,在上面的例子中,我写模块[]的方法很糟糕。这就是为什么它不起作用。请忽略我上午9:40的更新。我现在正在更正它,几分钟后会更新。它可能真的起作用了
上午10:08更新
好的,这是独家报道:在我早上9:40的时候,当我说“以上不起作用”时,是因为我的设置错误,错误的位置()。我纠正了这一点。我现在以标题避免全局定义
消息是它适用于一个操纵。一旦我将操纵复制到另一个单元格,计数器将在两个操纵之间共享
下面是一个例子:(更正了我在上午9点40分所说的内容)
只要存在操纵的一个副本,设置就会起作用。一旦我将操纵本身复制到新单元格并进行修改,第一个单元格就会更新。计数器是全局的:
所以,太糟糕了,这些解决方案不适合我。稍后将尝试函数上下文的事情。但需要先了解更多
下午12点更新
为了说明我现在所做的,在回答下面的MrWizard时,对于我拥有的每个“解算器”,我通过pn
预先确定其每个参数的名称,其中n
是解算器ID号。因此我有p1StepNumber、p2StepNumber、p3StepNumber、p1Solution、p2Solution、p3Solution等
然后,当我想调用解算器1时,我将p1*参数传递给它,返回时,它将返回解决方案和任何更新,保存在操纵控件->无区域中,以供以后调用,依此类推
因此,每个解算器的状态都作为Control->None变量保存/保存在操纵中。由于操纵是DynamicModule,因此在调用之间保存,甚至在我关闭M并重新打开它时也会保存
下面是一个屏幕截图,显示了“控制无”区域中我的操纵参数的部分列表。所有这些参数以及更多参数都包含在一个操纵中。当用户更改解算器时,整个UI也会更改,并为该解算器指定一个新的布局
由于使用了Leonid宏方法,我现在可以轻松地完成此操作:)
如果我可以将这些“保存在”每个解算器内,并将每个解算器作为一个单独的模块,每个解算器将保存自己的状态,每次需要刷新时,操纵将只向其传递UI参数,其他所有内容都保存在解算器内,它们所属的位置
甚至没有一个结构来管理它,这意味着我每次调用都有超过20个-
Remove["Global`*"]
Manipulate[
ctrl;
Print["in top of Manipulate"];
Grid[{
{"processA current total=", aResult},
{"processA current total=", bResult}
}],
Button["update A process", {ctrl++; aResult = processA[]}],
Button["update B process", {ctrl++; bResult = processB[]}],
{{ctrl, 0}, None},
{{aResult, 0}, None},
{{bResult, 0}, None},
{{processA, Module[{},
(
If[! ValueQ[processA`total], processA`total = 0];
processA`total = processA`total + 1;
processA`total
) &]}, None},
{{processB, Module[{},
(
If[! ValueQ[processB`total], processB`total = 0];
processB`total = processB`total + 1;
processB`total
) &]}, None},
TrackedSymbols :> {ctrl}
]
Module[{total = 0}
, myAdd[] := (total += 1; Print["current total ", total])
]
In[2]:= myAdd[]
current total 1
In[3]:= myAdd[]
current total 2
In[4]:= myAdd[]
current total 3
In[5]:= Module[{total}, total]
Out[5]= total$562
In[6]:= Names["total*"]
Out[6]= {"total", "total$557", "total$562"}
In[7]:= total$557
Out[7]= 3
In[8]:= ??myAdd
Global`myAdd
myAdd[]:=(total$557+=1; Print[current total, total$557])
Manipulate[
{x, myAdd[]}
, {x, 1, 10}
, Initialization :>
Module[{total = 0}
, myAdd[] := (total += 1; total)
]
]
Manipulate[
{x, myAdd[]}
, {x, 1, 10}
, { myAdd
, Module[{total = 0}, (total += 1; total) &]
, None
}
]
Manipulate[
Module[{f, g}
, Module[{total = 0}, f[] := ++total]
; Module[{total = 0}, g[] := --total]
; Dynamic[{x, f[], g[]}]
]
, {x, 1, 10}
]
Manipulate[
n;
processA[] := (total = total + 1);
processB[] := (total = total + 1);
Grid[{{"module A total=", processA[]}, {"module B total=", processB[]}}],
Button["press to update state", n++],
{{n, 0}, None},
{{total, 0}, None},
TrackedSymbols :> {n}
]
Manipulate[
{x, myAdd[]},
{x, 1, 10},
{{total, 0}, None},
{{myAdd, (total += 1; total) &}, None}
]
Manipulate[ctrl;
Grid[{
{"processA current total=", aResult},
{"processA current total=", bResult}
}],
Button["update A process", {ctrl++; aResult = processA[]}],
Button["update B process", {ctrl++; bResult = processB[]}],
{{ctrl, 0}, None},
{{aResult, 0}, None},
{{bResult, 0}, None},
{{total1, 0}, None},
{{total2, 0}, None},
{{processA, (++total1) &}, None},
{{processB, (++total2) &}, None},
TrackedSymbols :> {ctrl}
]