问题
I'd like to ask if any one knows of any issues (performance or otherwise) if one were to define/put the module(s) used by the Manipulate expression, right inside the Manipulate expression itself, vs. in the initialization section, where normally it is done.
Both methods work, but the semantics are not the same when it comes to direct access to Manipulate dynamics from the module (vs. them being passed as arguments to the module, which is the better method actually, but I am trying something now)
I do not know how these things are implemented, but I am worried that if I put all the modules inside the Manipulate expression, then Manipulate will slow down when there are many modules there, since each time it needs to refresh the expression, the Mathematica FE will send to the kernel a now much larger expression to reevaluate/parse or whatever the correct term.
The Manipulate expression being refreshed now is much larger now since the modules are now part of the Manipulate expression itself, vs being in the initialization section, and this happen even though some of them might not be called in each refresh.
To help explain the question more, I made a small diagram below to show what I mean, a side-by-side comparing the 2 methods. Below that, I also put the small code examples used in the diagrams:
code for the The part-of-expression method
Manipulate[
foo[]:=Module[{},
x++
];
ctrl;
foo[],
Button["step",{ctrl++ }],
{{ctrl,0},None},
{{x,0},None},
TrackedSymbols:>{ctrl}
]
code for the module-in-initialization method
Manipulate[
ctrl;
foo[],
Button["step", {ctrl++ }],
{{ctrl, 0}, None},
{{x, 0}, None},
TrackedSymbols :> {ctrl},
Initialization :>
{
foo[] := Module[{},
x++
]
}
]
The question is: Will there be a performance hit in the modules-inside-manipulate expression method?
note added:
Btw, on my current small demo, I did NOT notice any performance difference in both methods, but this is just based on observing the response of the demo and no exact measurements. May be my understanding of the Initialization section of Manipulate was not correct all along. From help it says:
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.
And it looks like may be I interpreted this as meaning differently that what it is.
May be Manipulate was always evaluating all the modules each time as part of its expression refresh/update?
Either way, I would be happy if there turns out to be no performance difference of the 2 layouts, as from now on, I will put all the modules inside Manipulate expression itself, instead of in the Initialization section.
addition dec 19, 2001 11 pm I looked at Mr Wizard solution posted below. From what I see, looking at the Manipulate snapshot, the resulting code is equivalent to explicitly putting the module inside the Manipulate expression. Here is a screen shot showing both methods, and the resulting code (generate by the Manipulate Function, by using the snapshot option button) for each layout. We can see it is the same code.
But the trick that Mr Wizard used to allow a function be put in the Control->None, which is to write just foo
instead of foo[]
is something I would not have thought of. I always thought that one must write foo[]:=Module[...]
even if foo
takes no arguments. (actually I never even thought about it, I just naturally write [] at the end of each function name even if takes no arguments). Thanks for sharing this trick.
回答1:
I think this has to be application specific. You can insert Pause[1];
expressions before foo[]:=
in both examples to confirm that reevaluation does not take place in the Initialization
method, while it does in the other. The question of how much time it takes to evaluate your expressions is one that you are in the best position to answer. Why don't you put all your definitions in a big Do
loop and time it?
Also, while I would not normally recommend it, since you are working under constraints, perhaps you are open a hack of this nature:
Manipulate[
ctrl; foo[],
Button["step", {ctrl++}],
{{ctrl, 0}, None},
{{x, 0}, None},
{{foo, Module[{}, x++] &}, None},
TrackedSymbols :> {ctrl}
]
回答2:
Responding to your addition dec 19, 2001 11 pm:
As you can see in your own screen capture above, the code is not in fact the same. In the upper example the definition of foo
is inside the variable list of DynamicModule
and not in the body where it will be repeatedly evaluated. This I believe is exactly the functionality you desire, is it not?
You wrote:
But the trick that Mr Wizard used to allow a function be put in the Control->None, which is to write just foo instead of foo[] is something I would not have thought of. I always thought that one must write foo[]:=Module[...] even if foo takes no arguments. (actually I never even thought about it, I just naturally write [] at the end of each function name even if takes no arguments). Thanks for sharing this trick.
Don't miss the mechanism by which this works. (By the way, I really hated writing Module[{} ...
but I copied it from your code. Please let us avoid that construct in the future.)
It is generally correct to use the form
function[]
rather thanfunction
when you want to perform an action. Though it is quite possible, it goes against the nature and syntax of Mathematica to trigger an action with only the function name. It also makes it hard to handle the function itself without triggering evaluation.You can get the behavior above by using
&
with noSlot
arguments.
If we define doSomething = Print["Something Done!"] &
we then call it with doSomething[]
to print the string. We can still write or pass the function itself using doSomething
without triggering evaluation.
来源:https://stackoverflow.com/questions/8550358/any-performance-issues-with-defining-modules-as-part-of-manipulate-expression-vs