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中制作结构的选择不是最好的,但我想先看看它是否可行)
方法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需要一个真正的结构/记录来帮助人们在较大的程序中组织变量.