SaveDefinitions
is a nice option of Manipulate
. It causes Manipulate
to store any definitions used for its creation inside the Manipulate panel. A Manipulate made this way can be copied to an empty notebook and will still work on its own. Additionally, your working notebook containing many such Manipulates also doesn't turn into a flurry of pink boxes with printed error messages below it upon opening. Great!
However, all this goodness has its dark side which can bite you real hard if you are not aware of it. I've had this in a notebook I had been working on for a few days, but I present you with a step-by-step toy example scenario which recreates the problem.
In this scenario you want to create a Manipulate
showing a plot of a nice wavy function, so you define this (please make a window size like this, this is important):
The definition is nice, so we keep it for the next time and make it an initialization cell. Next we add the Manipulate
, and execute it too.
f[x_] := x^2
Manipulate[
Plot[n f[x], {x, -3, 3}],
{n, 1, 4},
SaveDefinitions -> True
]
All works great, the Manipulate really shines, it is a good day.
Just being your paranoid self you check whether the definition is OK:
Yeah, everything still checks out. Fine. But now it occurs to you that a better wavy function would be a sine, so you change the definition, execute, and being paranoid, check:
Everything still fine. You're ready from a day's hard work you save your work and quit. [Quit kernel]
Next day. You start your work again. You evaluate the initialization cells in your notebook. Definition still good? Check.
Now, you scroll down to your Manipulate box (no need to re-execute thanks to the SaveDefinitions
), play a little with the slider. And scroll back up.
Being the paranoid you, you once more check the definition of f:
Lo and behold, someone has changed the definition behind your back! And nothing executed between your first and second Information
(?) check according to the In[] numbers (In[1]
: def of f, In[2]
first ?, In[3]
second ?).
What happened? Well, it's the Manipulate
of course. A FullForm
reveals its internal structure:
Manipulate[Plot[n*f[x],{x, -3, 3}],{{n, 2.44}, 1, 4},Initialization:>{f[x_] := x^2}]
There you have the culprit. The initialization part of the box defines f again, but it's the old version because we didn't re-evaluate the Manipulate
after modifying its definition. As soon as the manipulate box gets on the screen, it is evaluated and you've got your old definition back. Globally!
Of course, in this toy example it is immediately clear something strange is happening. In my case, I had a larger module in a larger notebook in which I, after some debugging, had changed a small part. It seemed to work, but the next day, the same bug that had bugged me before hit again. It took me a couple of hours before I realized that one of the several Manipulates that I used to study the problem at hand from all sides was doing this.
Clearly, I'm tempted to say, this is unwanted behavior. Now, for the obligatory question: what can we do to prevent this behind-your-back behavior of Manipulate
from occurring other than re-executing every Manipulate
in your notebook each time you change a definition that might be used by them?
SaveDefinitions -> True
option inManipulate
you just should not use initialization cell for the same task! It is similar to creating two initialization cells in the same Notebook with different definitions for the same symbol... – DoellingManipulate
. – Doelling