Распечатать динамическую переменную внутри DynamicModule - PullRequest
6 голосов
/ 11 октября 2011

Почему не значение b получает напечатано в следующем примере, а имя символа?Как я могу заставить печать фактического динамического значения переменной?

a = {1, 2, 3};

DynamicModule[{b},
 Print[Dynamic[b]];
 {Dynamic[a], Dynamic[b]}
 ,
 Initialization :> (b = Length[a]; a = a + 2)
 ]

вывод:

b$107

Out[2]= {{3, 4, 5}, 3}

Редактировать (после прочтения ваших ответов / комментариев):

Рассмотрим более простой пример без кода Initialization (чтобы обойти пример WReach):

a = {1, 2, 3};

DynamicModule[{b = Length[a]},
 Print[Dynamic[b]];
 {Dynamic[a], Dynamic[b]}
 ]

output:

During evaluation of In[4]:= b$602

Out[5]= {{1, 2, 3}, 3}

Обратите внимание, что этоПример делает то, что я хочу, если я использую Module вместо DynamicModule или пропускаю Dynamic из строки Print.Мои опасения:

  1. Почему во втором примере неправильно выводится значение b ?Инициализация отсутствует, которая (согласно справке) содержит «выражение для оценки при первом отображении модуля DynamicModule».Также согласно справке: «Когда DynamicModule сначала оценивается, сначала выполняются начальные назначения для локальных переменных, а затем оценивается любая настройка для опции Initialization

  2. справка должна гласить: «Инициализация: выражение для оценки при первом отображении результата *1039* DynamicModule», означающее, что оператор Print на экране не является «результатом» DynamicModule.Если это правильно, то (и только тогда) я понимаю, почему утверждение Print не означает, что объект Dynamic отображается правильно.

Ответы [ 2 ]

6 голосов
/ 11 октября 2011

Я полагаю, это происходит потому, что объект Dynamic b не отображался во время вызова оператора Print, и, следовательно, инициализация не была выполнена. Насколько я помню, функциональность Dynamic не работает, пока она на самом деле не отображается наглядно.

См. Почему это не сработает? Динамический в Select для получения дополнительной информации.


В ответ на ваше обновление моя теория состоит в том, что оператор Dynamic внутри Print никогда не отображается FrontEnd, и поэтому он фактически никогда не инициализируется. Таким образом, он остается уникальным заполнителем, ожидающим заполнения динамическим значением b, когда он, наконец, отобразится.

Из приведенного ниже примера видно, что оценка RHS назначения происходит перед телом Print, по крайней мере, по мере порядка отображения во FrontEnd. Далее, мы видим, что Print «входит внутрь» Dynamic и берет уникальное имя символа, созданное DynamicModule, и печатает его. Мы можем использовать ToString, чтобы Print отображал все выражение как есть. Аналогично, если мы извлечем имя символа из этой строки и преобразуем его в фактический символ, перед печатью мы получим ожидаемое значение, которое действительно уже было присвоено.

alarm := (Print["Initialized!"]; 3)

DynamicModule[{b = alarm},
  Print @ ToString @ Dynamic @ b;
  Print @ Symbol @ StringTake[ToString@Dynamic@b, {9, -2}];
  Print @ Dynamic @ b;
];

Выход:

Initialized!

Dynamic[b$701]

3

b$701 
3 голосов
/ 12 октября 2011

Ключевое поведение описано в разделе Дополнительная информация документации для DynamicModule :

DynamicModule сначала дает уникальныйимена для локальных переменных в expr , точно так же как Module , затем оценивает полученное выражение и затем возвращает версию этого обернутого в DynamicModule .

Точная последовательность событий становится более очевидной, если добавить к параметру Initialization оператор Print, таким образом:

a = {1, 2, 3};

DynamicModule[{b},
 Print[Dynamic[b]];
 {Dynamic[a], Dynamic[b]}
 ,
 Initialization :> (b = Length[a]; Print["init:", b]; a = a + 2)
 ]

, в результате чего получится три ячейки:

        b$107

Out[7]= {{3, 4, 5}, 3}

        init:3

Ячейка, содержащая b$107, является результатом Print внутри DynamicModule.Затем мы получаем ячейку результата (помеченную Out[7] здесь).Наконец, мы видим третий вывод ячейки с помощью оператора Print в Initialization.

Если вы проверите выражение ячейки Out[7], вы обнаружите, что локализованная переменная равна b$$.Это отличается от переменной в первой ячейке, которая равна b$107.Это различие связано с «двойной областью видимости», описанной в документации DynamicModule.Ячейка b$107 содержит поле Dynamic, что можно увидеть, если мы присвоим значение b$107.

Обновление

В ответ на обновленноевопрос ...

Возвращаясь к исходному выражению (без дополнительных Print в Initialization), точная последовательность событий выглядит следующим образом:

Во-первых, телоDynamicModule оценивается после предоставления "уникальных имен локальным переменным [...] точно так же, как Module ".То есть это выражение вычисляется:

Print[Dynamic[b$107]]; {Dynamic[a], Dynamic[b$107]}

Результатом этого выражения является список {Dynamic[a], Dynamic[b$107]}.В качестве побочного эффекта создается динамическая ячейка, содержащая b$107, но эта ячейка теперь удалена из дальнейшего рассмотрения, поскольку она не является частью результата оценки.Теперь «версия [{Dynamic[a], Dynamic[b$107]}] обернута в DynamicModule » и возвращена.Это оценивается и неявно печатается для получения выражения выходной ячейки, подобного этому:

Cell[BoxData[
 DynamicModuleBox[{$CellContext`b$$ = 3}, 
  RowBox[{"{", 
   RowBox[{
    DynamicBox[ToBoxes[$CellContext`a, StandardForm],
     ImageSizeCache->{57., {2., 8.}}], ",", 
    DynamicBox[ToBoxes[$CellContext`b$$, StandardForm],
     ImageSizeCache->{7., {0., 8.}}]}], "}"}],
  DynamicModuleValues:>{},
  Initialization:>($CellContext`b$$ = 
    Length[$CellContext`a]; $CellContext`a = $CellContext`a + 2)]], "Output"]

Обратите особое внимание, что b$107 переименовано в $CellContext`b$$ как функция DynamicModule локализации символа.Выражение Initialization теперь оценивается, когда поле отображается и отображается.

Ключевым моментом является то, что напечатанная ячейка, содержащая b$107, никак не связана с последней ячейкой DynamicModule.

...