Подтвердить что ты не робот

Как определить часть определения управляющей переменной Manipulate для уменьшения дублирования кода

Это немного связано с этим вопросом

Определить элемент управления как переменную в Mathematica

Но этот вопрос не ответил на мою проблему, поскольку он говорит о полном определении контроля. (Я также пробовал некоторые из трюков, показанных там, но они не работают для моей проблемы).

Теперь я спрашиваю об определении только для части элемента управления. (Также очень сложно следить за старым вопросом, используя этот формат форума. Поскольку использование крошечной области комментариев трудно задавать и показывать больше, задавая новый вопрос, где пространство больше, и можно вставлять код и изображений).

Все попытки, которые я сделал, не работают. Начну с простого примера, чтобы объяснить проблему.

Предположим, что вы хотите написать

Clear["Global`*"];

Manipulate[Plot[f*g, {x, -1, 1}],
 Grid[{
   {Style["f(x)="], 
    PopupMenu[Dynamic[f], {x, x^2, x^3}, ImageSize -> Tiny]},{Style["g(x)="], 
    PopupMenu[Dynamic[g], {x, x^2, x^3}, ImageSize -> Tiny]}
   }]
 ]

вы можете видеть, что в каждом определении элемента есть дублирование кода. (такие вещи, как ImageSize, Spacings- > и многие другие настройки украшений, повторяются снова и снова для каждого элемента управления.

enter image description here

Что будет здорово, если я смогу написать что-то вроде

Manipulate[Plot[f*g, {x, -1, 1}],
 Grid[{
   {Style["f(x)="], PopupMenu[Dynamic[f], [email protected]@v]},
   {Style["g(x)="], PopupMenu[Dynamic[g], [email protected]@v]}
   }],

 Initialization :>
  (
   v = {{x, x^2, x^3}, ImageSize -> Tiny}
   )
 ]

Но это не работает. Я провожу много других вещей вдоль вышеприведенной строки, и ничего не работает. Как

{Style["f(x)="], PopupMenu[Dynamic[f], v]},

и

{Style["f(x)="], PopupMenu[Dynamic[f], [email protected]]}

и

Manipulate[Plot[f*g, {x, -1, 1}],

 {{v, {{x, x^2, x^3}, ImageSize -> Tiny}}, None},
 Grid[{
   {Style["f(x)="], PopupMenu[Dynamic[f], [email protected]]},
   {Style["g(x)="], PopupMenu[Dynamic[g], v]}
   }]
 ]

не может заставить его работать.

Но вот правила игры: Это будет для демонстрации, поэтому код должен начинаться с Manipulate. Не может быть Module Out Manipulate. Кроме того, не может использовать Hold и его друзей. Но можно использовать Unevaluated.

Я надеялся, что здесь у экспертов может быть трюк. Воля уменьшит размер кода, если это возможно, так как многие из элементов управления, которые у меня есть, содержат множество "опций", подобных вышеперечисленным, которые являются одинаковыми, и возможность выполнить вышеизложенное сделает код более легким для чтения и управления.

спасибо,

пс. То, что я прошу, похоже на то, что вы делаете для вариантов Plot, где можно использовать SetOptions для установки некоторых стандартных параметров по умолчанию, чтобы каждый раз не приходилось дублировать их для каждой команды Plot. Но в этом случае нет такой вещи.

Обновление

Используя метод, показанный Леонидом ниже (макро-трюк), я хотел использовать его, чтобы помочь мне определить количество элементов управления, используя одну общую настройку. Это то, что я пробовал:

Manipulate[{x, y},

 [email protected][
   {
    control1 = Function[{var, initialValue, str, from, to, incr},
      {
       {{var, initialValue, str}, from, to, incr, ImageSize -> Tiny}
       }
      ,
      HoldAll
      ]
    },

   {
      [email protected][x, 0, "x=", 0, 1, .1],
      [email protected][y, 0, "y=", 0, 2, .1],
      [email protected][z, 0, "z=", 0, 10, .1]
    }, 

   ]
 ]

Проблема заключается только в дополнительном {} во всем этом, иначе он будет работать. Будут продолжать пытаться решить это. Но приблизиться. Tried Sequence [] и Flatten [.., 1] и т.д., Но еще не может этого сделать. Делать больше кофе, должно помочь.

Обновление 2

Ниже приведен пример использования метода Саймона для определения общего определения для нескольких элементов управления. Таким образом, можно использовать его для уменьшения дублирования кода для общих опций при наборе отдельных элементов управления.

Обратите внимание, что нужно было использовать Control[], чтобы заставить его управлять.

Manipulate[{x, y, z},

 Dynamic[Grid[{
    {control1[x, 0, "x=", 0, 1, .1]},
    {control1[y, 0, "y=", 0, 2, .1]},
    {control1[z, 0, "z=", 0, 10, .1]}
    }]],

 {{control1, 
   Function[{var, initialValue, str, from, to, incr}, 
    Control[{{var, initialValue, str}, from, to, incr, 
      ImageSize -> Tiny}], HoldFirst]}, None}

 ]

enter image description here

Обновление 3

И получил метод Леонида, чтобы работать и на более чем одном контроле. Хитрость заключается в использовании Control[]. Невозможно использовать простой старый {{x,0,"x"},...} [EDIT, да, вы можете, просто нужен метод Sequence @@, как показано ниже, с помощью обновления Leonid.].

Вот он:

Manipulate[{x, y, z},

 [email protected][
   {
    control1 = Function[{var, initialValue, str, from, to, incr},
      Control[{{var, initialValue, str}, from, to, incr, 
        ImageSize -> Tiny}]
      , HoldAll
      ]
    },

   Grid[{
     {control1[x, 0, "x=", 0, 1, .1]},
     {control1[y, 0, "y=", 0, 2, .1]},
     {control1[z, 0, "z=", 0, 10, .1]}
     }]

   ]
 ]

enter image description here

Я попытаюсь интегрировать один из этих методов в мою основную демонстрацию (имеет более 600 строк кода только для макета управления до сих пор и растет с каждым разом, мы надеемся, что эти методы уменьшат это немного)

Обновление 9/26/11. 7 вечера

Мне показалось, что я публикую вид "птичьего глаза" на сохранение кода, используя "макросы" для определения элементов управления, которые содержат много общего кода котельной. Вот скриншот до и после.

Еще раз спасибо за ответ и помощь.

enter image description here

4b9b3361

Ответ 1

Как насчет этого

Manipulate[Plot[f*g, {x, -1, 1}],
 [email protected]
  With[{styleAndpopup = 
      Function[{st, fun}, 
         {
           Style[st], 
           PopupMenu[Dynamic[fun], {x, x^2, x^3}, ImageSize -> Tiny]
         }, 
         HoldAll]},
    Grid[{styleAndpopup["f(x)=", f], styleAndpopup["g(x)=", g]}]]]

Это на самом деле крошечный пример генерации кода на работе, так как если вы посмотрите на FullForm результирующего Manipulate, вы увидите то же самое выражение, с которого вы начали сначала. styleAndpopup на самом деле не функция здесь, а макрос, локально определенный с помощью With.

ИЗМЕНИТЬ

По запросу OP - обобщение на многие элементы управления. Самое простое исправление - вставить [email protected]@... как Sequence @@ {[email protected][.... Однако есть и другие посторонние вещи, которые можно удалить:

Manipulate[{x, y}, 
 [email protected][{control1 = 
     Function[{var, initialValue, str, from, to, incr}, 
       [email protected]{{var, initialValue, str}, from, to, incr, ImageSize -> Tiny}, 
       HoldAll]}, 
   Sequence @@ {
     control1[x, 0, "x=", 0, 1, .1], 
     control1[y, 0, "y=", 0, 2, .1], 
     control1[z, 0, "z=", 0, 10, .1]}]]

Ответ 2

Я собирался дать решение почти так же, как Леонид, и использовать With для вставки кода, но он избил меня до этого, так что здесь альтернативный путь. Определите динамическую локальную функцию с помощью ControlType -> None, которая делает ваш стиль:

Manipulate[Plot[{f, g + 1}, {x, -1, 1}], 
 Dynamic[Grid[{{Style["f(x)="], pu[f]}, 
       {Style["g(x)="], pu[g]}}]], 
{{pu, Function[{f}, PopupMenu[Dynamic[f], {x, x^2, x^3}, ImageSize -> Tiny], 
        HoldFirst]}, None}]

Кстати, Style[] in Style["f(x)="] избыточен, так как вы фактически не устанавливаете никаких стилей...

Ответ 3

Можно сделать следующее:

Manipulate[
  Plot[f*g, {x, -1, 1}]
, Grid[
    { {Style["f(x)="], PopupMenu[Dynamic[f], opts]}
    , {Style["g(x)="], PopupMenu[Dynamic[g], opts]}
    }
  ]
] /. opts -> Sequence[{x, x^2, x^3}, ImageSize -> Tiny]

Если у вас есть привычка присваивать вниз значения символам, имена которых не начинаются с $, тогда было бы разумно обернуть все это в Block[{x, opts}, ...] в случае, если x и opts имеют глобально определенные значения.

Аналогичный метод возможен для случая нескольких элементов управления:

Manipulate[
  {x, y, z}
, Grid[
    { {control1[x, 0, "x=", 0, 1, .1]}
    , {control1[y, 0, "y=", 0, 2, .1]}
    , {control1[z, 0, "z=", 0, 10, .1]}
    }
  ]
] /. control1[var_, initialValue_, str_, from_, to_, incr_] :>
       Control[{{var, initialValue, str}, from, to, incr, ImageSize -> Tiny}]