SaveDefinitions
- это хороший вариант для Manipulate
. Он заставляет Manipulate
сохранять любые определения, используемые для его создания, внутри панели Manipulate Созданное таким образом манипулирование может быть скопировано в пустую записную книжку и по-прежнему будет работать самостоятельно.Кроме того, при открытии ваша рабочая записная книжка, содержащая множество таких манипуляций, также не превращается в шквал розовых ящиков с напечатанными под ними сообщениями об ошибках. Отлично!
Однако у всего этого добра есть темная сторона, которая может сильно вас укусить, если вы этого не осознаете. У меня есть это в записной книжке, над которой я работал несколько дней, но я представляю вам с пошаговым примером сценария игрушки, который воссоздает проблема.
В этом сценарии вы хотите создать Manipulate
, показывающий график красивой волнистой функции, поэтому вы определяете это (пожалуйста, сделайте размер окна подобным этому, это важно):
Определение хорошее, поэтому оставим его до следующего раза и сделаем ячейкой инициализации. Затем мы добавляем Manipulate
и тоже выполняем его.
f[x_] := x^2
Manipulate[
Plot[n f[x], {x, -3, 3}],
{n, 1, 4},
SaveDefinitions -> True
]
Все работает отлично, Manipulate действительно сияет, сегодня хороший день.
Просто будучи параноиком, вы проверяете, подходит ли определение:
Да, все еще проверяется. Хорошо. Но теперь вам приходит в голову, что лучшей волнистой функцией была бы синусоида, поэтому вы меняете определение, выполняете и, будучи параноиком, проверьте:
Все по-прежнему в порядке. Вы готовы после тяжелого рабочего дня сохранить свою работу и уйти. [Выйти из ядра]
На следующий день. Вы снова начинаете свою работу. Вы оцениваете ячейки инициализации в своей записной книжке. Определение все еще хорошее? Проверьте.
Теперь вы прокручиваете вниз до поля «Манипулировать» (не нужно повторновыполнить благодаря SaveDefinitions
), поиграйте немного с ползунком. И прокрутите назад.
Будучи параноиком, вы еще раз проверьте определение f:
И вот, кто-то изменил определение за вашей спиной! И ничего не было выполнено между вашей первой и второй проверкой информации
(?) В соответствии с числами In [] ( In [1]
: def of f, In [2]
первый?, В [3]
второй?).
Что произошло? Ну, конечно, это Manipulate
. FullForm
раскрывает его внутреннюю структуру:
Manipulate[Plot[n*f[x],{x, -3, 3}],{{n, 2.44}, 1, 4},Initialization:>{f[x_] := x^2}]
Вот и виноват. Часть инициализации блока снова определяет f, но это старая версия, потому что мы не переоценивали Manipulate
после изменения его определения. Как только поле манипулирования появляется на экране, оно оценивается, и вы получаете обратно свое старое определение. Глобально!
Конечно, в этом игрушечном примере сразу видно, что происходит что-то странное. В моем случае у меня был модуль большего размера в большом ноутбуке, в котором я после некоторой отладки изменил небольшую часть. Казалось, что это сработало, но на следующий день та же ошибка, которая беспокоила меня, прежде чем ударила снова. Мне потребовалось несколько часов, прежде чем я понял, что это делает один из нескольких манипуляций, которые я использовал для изучения данной проблемы со всех сторон.
Ясно, что мне хочется сказать, что это нежелательное поведение. Теперь, что касается обязательного вопроса: , что мы можем сделать, чтобы предотвратить такое скрытое поведение Manipulate
, кроме повторного выполнения каждого Manipulate
в вашей записной книжке. когда вы измените определение, которое могло бы использоваться ими?