Wolfram mathematica Mathematica中有没有简单的机制来创建具有持久状态的模块?

Wolfram mathematica Mathematica中有没有简单的机制来创建具有持久状态的模块?,wolfram-mathematica,Wolfram Mathematica,在C语言中,当我在函数中定义局部变量时,如果我想在调用之间保存局部变量值,我通常会在变量旁边添加static这个词 这给了我变量名的局部范围保护,但同时,变量值是持久的。模拟一个保存自己私有状态的简单对象非常有用 是否可以在Mathematica中使用Module[]?或者动态模块[] (我们知道默认情况下,Module[]不会保存局部变量状态,但是使用DynamicModule[]?)怎么样 不使用包。使用它的上下文位于操纵[]中 任何模块[]都不能在外部操作。因此,一切都必须是这样的: M

在C语言中,当我在函数中定义局部变量时,如果我想在调用之间保存局部变量值,我通常会在变量旁边添加static这个词

这给了我变量名的局部范围保护,但同时,变量值是持久的。模拟一个保存自己私有状态的简单对象非常有用

是否可以在Mathematica中使用
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}
]