In C, I used to add the word static next to a variable when I define a local variable inside a function if I wanted the local variable value saved between calls.
This gave me the local scope protection of the variable name, but at the same time, the variable value was persistent. Was very useful to emulate a simple object which saves its own private state.
http://en.wikipedia.org/wiki/Local_variable#Static_local_variables
Is it possible to emulate this in Mathematica using Module[]
? or DynamicModule[]
?
(we know Module[]
does not save local variables state by default, but What about using DynamicModule[]
?)
No uses of packages. The context of using this is inside a Manipulate[]
.
No Module[]
can be outside Manipulate. Hence everything has to be something like this:
Manipulate[
foo[]:=Module[{a,b,c},....];
boo[]:=Module[{a,b,c},....];
... foo[] ..
... boo[]...
..,
control_variables...,
Initialization:>
(
.... global area....
)
]
I tried using DynamicModule
in place of Module[]
above to do this, but DynamicModules
can't be called as functions? and I could not figure how to do it.
question is: is it possible to make a function remember the value of its local variables between calls, as one can do using C with local static variables for example?
of course, one can't save the state in global variables, this the whole point of me asking this question. I'd like the Module state saved in a context that belongs to that Module only.
I am not asking for any advanced OO emulation. Just wanted to save few local variables used by a Module in a name scope that belong to that Module instead in a global context and have them be persistent between calls to the Module.
Update
To be clear, here is a very basic C example
#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
$
Update 8:45 AM
This is for WReach solution. Here is what I tried:
Manipulate[
n;
Module[{total = 0},
processA[] :=
(
total = total + 1
)
];
Module[{total = 0},
processB[] :=
(
total = total + 1
)
];
Grid[{
{"module A total=", processA[]},
{"module B total=", processB[]}
}],
Button["press to update state", n++],
{{n, 0}, None},
TrackedSymbols :> {n}
]
The total remain 1 each time I hit the button. It is not saving the last value.
Update 9:13 AM
For WReach solution inside Manipulate:
Here is a test:
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}
)
]
)
]
On its own, it seems to work. But when I made a copy of the cell, and paste it to new cell. Then run the second Manipulate, to update the total there, then went back to the first Manipulate to update the total there, I see it is using the updated total from the second Manipulate. Hence it is global.
This is not allowed in a demo. Snap-shots are taken, and they can't share state (no global variables are allowed in a demo. The initialization section must not contain global shared data. But can contain functions that are called via parameters only from the Manipulate expression, no problem.
update 9:40 AM
Reply to Mr Wizard second example below, for the pattern he showed, which is the following:
Manipulate[
{x, myAdd[]},
{x, 1, 10},
{{total, 0}, None},
{{myAdd, (total += 1; total) &}, None}
]
The problem with this, is that the name total
can not be used by 2 different functions. The name space for total
is across the whole Manipulate. What I'd want, using this pattern is something like this:
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}
]
You see, in the above, processA has its own local total, and processB as well. Same local name. The above does not work. If I replace the above with the following to make it 'work'
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}
]
Then processA and processB now share the same total variable. This defeats the whole point of having each be in separate name space, and yet be persistent over life time of call invocations.
Update 10 AM
Opps, I had bad way to writing that Module[] in the above example. That is why it was NOT working. Please ignore my 9:40 AM update. I am correcting it now, and will update in few minutes. It might actually be working.
update 10:08 AM
Ok, here is the scoop: In my 9:40 AM when I said "the above does not work", is because I had the setup wrong, wrong place of (). I corrected this. I am now showing the solution refered to below by WReach under the title Avoiding Global Definitions
The news is that it works for ONE manipulate. Once I copy the manipulate to another cell, the counters are shared between the 2 manipulates.
Here is an example: (corrected version of what I had above in 9:40 AM)
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[{total = 0}, ( total = total + 1; total) &]},
None},
{{processB, Module[{total = 0}, (total = total + 1; total) &]}, None},
TrackedSymbols :> {ctrl}
]
The set up works, as long as there is one copy of the Manipulate. Once I copy the Manipulate itself to new cell, and modify that, the first gets updated. counters are global:
So, too bad, these solution do not work for me. Will try later the function context thing. But need to learn more about it first.
update 12 PM
To illustrate what I do now, in reply to MrWizard below, for each 'solver' I have, I pre-fix the name of each of its parameters by pn
, where n
is a solver ID number. So I have p1StepNumber, p2StepNumber, p3StepNumber, p1Solution, p2Solution, p3Solution, etc...
Then when I want to call solver 1, I pass it the p1* parameters and on return it returns back the solution and any updates, to be saved in the Manipulate Control->None area for later call, and so on.
Hence, state of each solver is kept/saved inside the Manipulate as Control->None variables. Since Manipulate is DynamicModule, these are saved between calls, and even when I close M and reopen it.
Here is a screen shot of partial listing of my Manipulate parameters in the Control-None area, to illustrate. all of these and much more are in one Manipulate. When user changes solver, the whole UI changes as well with a new layout specific for that solver.
Thanks to the use of Leonid Macro method, I am able to now do this easily :).
It would be better if I can save these 'inside' each solver, and have each solver be a separate Module, where each solver will save it own state, and Manipulate will just pass it the UI parameter each time it needs to refresh, and everything else is saved inside the solver(s) where they belong.
Not having even a struct to manage this, means each call I make has over 20-30 parameters to it. Since I need to pass the solver all of its state each time, and get it back with it returns. It is not too bad, I just have to get used to making calls with 30 parameters each time, which is something I am not used. But I see no other clean way around it so far. That is why I asked this question.
update 12/24/11 6 PM This is below response to suggestion by Szabolcs and telefunkenvf14 to use function context name.
The conclusion I found is that this method does not work either. Same issue as the other methods.
Once I make a copy of the Manipulate itself, the variables become shared among the 2 copies of the Manipulates.
Below is an example showing the problem:
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}
]
Now I copied the above into a new cell and clicked on the buttons, and I see the counters now advance from the values in the previous copy of Manipulate. So process`A is shared. It is local to each specific function.
Exactly the same issue with the other method tried, so this method does not work for me.
Try this:
Module[{total = 0}
, myAdd[] := (total += 1; Print["current total ", total])
]
Use:
In[2]:= myAdd[]
current total 1
In[3]:= myAdd[]
current total 2
In[4]:= myAdd[]
current total 3
For practical purposes, the module variable total
is visible only to myAdd
. Module
implements this by creating a new unique symbol whose name is generated from the supplied symbol (total
in this case). You can see this by evaluating an expression such as:
In[5]:= Module[{total}, total]
Out[5]= total$562
We can actually access the symbol used by myAdd
:
In[6]:= Names["total*"]
Out[6]= {"total", "total$557", "total$562"}
In[7]:= total$557
Out[7]= 3
We can also see the effect of the renaming by examining the definition of myAdd
:
In[8]:= ??myAdd
Global`myAdd
myAdd[]:=(total$557+=1; Print[current total, total$557])
Use Inside Manipulate
We can use this technique inside Manipulate
thus:
Manipulate[
{x, myAdd[]}
, {x, 1, 10}
, Initialization :>
Module[{total = 0}
, myAdd[] := (total += 1; total)
]
]
Avoiding Global Definitions
If we are desperate to avoid a global definition of myAdd
, we can do this:
Manipulate[
{x, myAdd[]}
, {x, 1, 10}
, { myAdd
, Module[{total = 0}, (total += 1; total) &]
, None
}
]
This way, the definition of myAdd
is localized within the Manipulate
. Note, however, that the symbol myAdd
is still global, as are x
and total
. This is due to the fact that the entire Manipulate
expression is read into the global context. If this is unsatisfactory, then we would have to place the entire expression into another context -- there is no avoiding the fact that symbols have to live in some context.
Once More Into The Breach
Okay, here is another attempt to address the added requirements:
Manipulate[
Module[{f, g}
, Module[{total = 0}, f[] := ++total]
; Module[{total = 0}, g[] := --total]
; Dynamic[{x, f[], g[]}]
]
, {x, 1, 10}
]
This solution has the following features:
f
and g
are localized to the celltotal
are isolated from one another, and localized to the celltotal
variables are not reset to zero whenever you manipulate x
If I understand your needs, and I am not sure I do, then the form I suggested in this post may do what you want:
https://stackoverflow.com/a/8552728/618728
That is, using controls like: {{x, 0}, None}
Adapting your appended example, does this work?
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}
]
Adapting WReach's recent example:
Manipulate[
{x, myAdd[]},
{x, 1, 10},
{{total, 0}, None},
{{myAdd, (total += 1; total) &}, None}
]
Here is an example using your latest question update. As far as I can tell this works. I suggest you find a way to work around the need for separate symbols.
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}
]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With