Как определить часть определения управляющей переменной Manipulate, чтобы уменьшить дублирование кода - PullRequest
12 голосов
/ 26 сентября 2011

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

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

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

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

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

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

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], Evaluate@Sequence@v]},
   {Style["g(x)="], PopupMenu[Dynamic[g], Evaluate@Sequence@v]}
   }],

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

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

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

и

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

и

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

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

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

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

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

спасибо,

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

update

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

Manipulate[{x, y},

 Evaluate@With[
   {
    control1 = Function[{var, initialValue, str, from, to, incr},
      {
       {{var, initialValue, str}, from, to, incr, ImageSize -> Tiny}
       }
      ,
      HoldAll
      ]
    },

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

   ]
 ]

Проблема - просто лишняя {} во всем, иначе она будет работать.Будем продолжать пытаться решить это.Но приближаемся.Пробовал 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"},...} [РЕДАКТИРОВАТЬ, да, вы можете, просто нужен метод Sequence @@, как показано ниже обновлением Leonid.].

Вот оно:

Manipulate[{x, y, z},

 Evaluate@With[
   {
    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 строк кодачто касается макета элемента управления, который пока растет и растет с каждой минутой, то, надеюсь, эти методы значительно сократят его)

Обновление от 26.09.11.19:00

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

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

enter image description here

Ответы [ 3 ]

10 голосов
/ 26 сентября 2011

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

Manipulate[Plot[f*g, {x, -1, 1}],
 Evaluate@
  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.

EDIT

По запросу OP - обобщение для многихуправления.Самый простой способ - вставить Sequence@@... как Sequence @@ {First@control1[....Тем не менее, есть некоторые посторонние вещи, которые также могут быть удалены:

Manipulate[{x, y}, 
 Evaluate@With[{control1 = 
     Function[{var, initialValue, str, from, to, incr}, 
       Unevaluated@{{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]}]]
7 голосов
/ 26 сентября 2011

Я собирался дать решение, почти такое же, как у Леонида, и использовать 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[] в Style["f(x)="] является избыточным, так как вы фактически не устанавливаете какие-либо стили ...

1 голос
/ 26 сентября 2011

Можно было бы сделать это:

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}]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...