使用Manipulate中的结构来帮助管理控制变量,如何初始化

Nas*_*ser 5 struct wolfram-mathematica initialization

我不确定如何初始化Mathematica中的结构以与Manipulate一起使用,以帮助我更好地组织我拥有的许多控制变量.

我将举几个例子,这有助于说明问题.

这是最基本的操作:

方法1

Clear["Global`*"]
Manipulate[process[a, b],

 {{a, 1, "a"}, -10, 10, 1},
 {{b, 2, "b"}, -10, 10, 1},

 Initialization :> 
  {
   process[a_, b_] := Module[{}, Row[{"a=", a, " b=", b}]]
   }
 ]
Run Code Online (Sandbox Code Playgroud)

在我写的一个演示中,我有更多的控件.一些函数(例如上面名为process []的函数)最终必须使用15个或更多参数调用,这使得我很难维护.(我别无选择,不能真正考虑它).

所以,我正在尝试使用结构来收集这些变量.相关问题是这样的

在Mathematica中安全地设置"结构"

所以,接下来我尝试了下面的内容:(我知道在Mathematica中制作结构的选择不是最好的,但我想先看看它是否可行)

方法2

Clear["Global`*"]
Manipulate[process[myData],

 {{myData["a"], 1, "a"}, -10, 10, 1},
 {{myData["b"], 1, "b"}, -10, 10, 1},

 Initialization :> 
  {
   process[myData_] := 
    Module[{}, Row[{"a=", myData["a"], " b=", myData["b"]}]]
   }
 ]
Run Code Online (Sandbox Code Playgroud)

但上述方法无效.我明白了

Manipulate::vsform does not have the correct form for a variable specification
Run Code Online (Sandbox Code Playgroud)

所以,我想,好吧,让我自己填写结构,然后调用process []函数,所以我这样做了:

方法3

Clear["Global`*"]
Manipulate[
 (
  myData["a"] = a;
  myData["b"] = b;

  process[myData]
  ),

 {{a, 1, "a"}, -10, 10, 1},
 {{b, 1, "b"}, -10, 10, 1},

 Initialization :> 
  {
   process[myData_] := 
    Module[{}, Row[{"a=", myData["a"], " b=", myData["b"]}]]
   }
 ]
Run Code Online (Sandbox Code Playgroud)

这很有效.好的,但现在,因为我实际上正在使用Leonid宏方法来设置我的控件,这里解释

如何定义Manipulate控件变量定义的一部分以减少代码重复

现在我尝试了上面的方法(2),使用宏方法,它现在工作!但仍然存在的问题是如何初始化struct字段.这是上面的方法(2),使用宏

方法(2)使用Leonid宏方法设置控件

Clear["Global`*"]
Manipulate[process[myData],

 (*-- define 2 control variables, using the macro method --*)
 Evaluate@With[{s1 = Function[{struct},
      Grid[{
        {Manipulator[Dynamic[struct["a"]], {-20, 20, 0.1}]},
        {Manipulator[Dynamic[struct["b"]], {-2, 2, .5}]}
        }],
      HoldAll]
    },
   s1[myData]
   ],

 Initialization :> 
  {
   process[struct_] := Module[{},
     Text[Grid[{
        {"a=", struct["a"]},
        {" b=", struct["b"]}
        }]]
     ]
   }
 ]
Run Code Online (Sandbox Code Playgroud)

上面的工作,但myData没有初始化.这就是我的问题.我需要初始化它,以便屏幕上的初始显示将具有一些正确的值.

我可以使用Initialization部分来实现这一点,但是现在myData将变为全局,当我稍后创建Manipulate的快照时,这可能会导致问题,因为全局数据将在快照之间共享:

上面的方法(2),使用全局部分初始化

Clear["Global`*"]
Manipulate[process[myData],

 (*-- define 2 control variables, using the macro method --*)
 Evaluate@With[{s1 = Function[{struct},
      Grid[{
        {Manipulator[Dynamic[struct["a"]], {-20, 20, 0.1}]},
        {Manipulator[Dynamic[struct["b"]], {-2, 2, .5}]}
        }],
      HoldAll]
    },
   s1[myData]
   ],

 Initialization :> 
  {

   myData["a"] = 1;   (* now OK, but mydata is global *)
   myData["b"] = 1;

   process[struct_] := Module[{},
     Text[Grid[{
        {"a=", struct["a"]},
        {" b=", struct["b"]}
        }]]
     ]
   }
 ]
Run Code Online (Sandbox Code Playgroud)

当我尝试在Manipulate中初始化myData时,它不起作用,可能有一个技巧要做到这一点?

上面的方法(2),尝试使用None控件在Manipulate内初始化

Clear["Global`*"]
Manipulate[process[myData],

 (*-- define 2 control variables, using the macro method --*)
 Evaluate@With[{s1 = Function[{struct},
      Grid[{
        {Manipulator[Dynamic[struct["a"]], {-20, 20, 0.1}]},
        {Manipulator[Dynamic[struct["b"]], {-2, 2, .5}]}
        }],
      HoldAll]
    },
   s1[myData]
   ],

 {{myData["a"], 1}, None}, (*invalid syntax*)
 {{myData["b"], 1}, None},

 Initialization :> 
  {
   process[struct_] := Module[{},
     Text[Grid[{
        {"a=", struct["a"]},
        {" b=", struct["b"]}
        }]]
     ]
   }
 ]
Run Code Online (Sandbox Code Playgroud)

所以,我的问题是:我如何在上面的方法(2)中初始化myData,但是没有使它全局化?

我只是想补充一点,这是一个演示,所以规则是它必须以Manipulate [..]开头.外面没有模块.一切都必须在Manipulate内[...]

谢谢

更新:

我在上面的(3)中确定了模式,我在开始时自己填写结构.

它似乎工作得很好,并且调用了我现在更容易的许多函数,因为参数的数量大大减少了(我的函数被调用了20个参数!现在它被简化为5个参数,因为我打包了'将相关的控制变量放入一个结构中,现在更容易使用).不是一个完美的解决方案,但至少它有助于使代码更容易为我工作.

这就是'模式'现在的样子:

Manipulate[
 Module[{myData},

  (*fill in the struct *)
  myData["a"] = a;
  myData["b"] = b;
  myData["c"] = c;

  process[myData]
  ],
 (*-- define  control macro  --*)
 Evaluate@With[{s1 = Function[{var},
      Manipulator[Dynamic[var], {-20, 20, 0.1}], HoldAll]
    },
   Column[{s1[a], s1[b], s1[c]}]
   ],

 (*initialize fields of the struct, or the control variables*)
 {{a, 1}, None}, 
 {{b, 2}, None},
 {{c, 3}, None},

 Initialization :> 
  {
   process[myData_] := Module[{},
     Text[Grid[{
        {"a=", myData["a"]},
        {" b=", myData["b"]},
        {" c=", myData["c"]}
        }]]
     ]
   }
 ]
Run Code Online (Sandbox Code Playgroud)

我认为Mathematica需要一个真正的结构/记录来帮助人们在较大的程序中组织变量.