setdelayed внутри manipulate запускает цикл вычислений. Почему?

#wolfram-mathematica

#wolfram-mathematica

Вопрос:

Почему это:

 Manipulate[test[a_] := 2*b; test[c], {b, 0, 1}, {c, 0, 1}]
  

превращается в цикл вычисления?
Не следует Manipulate оценивать только при изменении b или c ?

Ответ №1:

Чтобы устранить проблему с минимальными изменениями, выполните

 Manipulate[
test[a_] := 2*b;
test[c], {b, 0, 1}, {c, 0, 1},
TrackedSymbols [Rule] {b, c}]
  

вместо этого (т.е. добавьте TrackedSymbols , чтобы сообщить Mathematica, что отслеживать на предмет изменений).

Ответ №2:

Да, Manipulate будет повторно вычисляться при изменении b или c , но также при test изменении — и test переназначается каждый раз, когда изменяется какое-либо из этих значений. Отсюда бесконечный цикл повторной оценки.

Как правило, следует избегать побочных эффектов в выражениях отображения таких конструкций, как Manipulate и Dynamic , чтобы избежать циклов вычисления, условий гонки и другого неожиданного поведения. В рассматриваемом случае я бы предложил удалить неявную зависимость от b in test и перенести ее определение за пределы Manipulate :

 test[b_, c_] := 2*b; Manipulate[test[b, c], {b, 0, 1}, {c, 0, 1}]
  

В реальном приложении могут возникнуть препятствия для такого простого рефакторинга, но ключевым моментом является удаление := из динамического выражения.