我在让 Manipulate
与分配给变量的代码一起工作时遇到问题,这些变量应该在 Manipulate
语句中进行评估。这是怎么回事......
test1={a,b,c};
Manipulate[test1,{a,0,10,.1},{b,0,10,.1},{c,0,10,.1}]
所以
{a, b, c}
没有更新。好的,无论如何,让我们强制执行 test1 的评估Manipulate[Evaluate[test1],{a,0,10,.1},{b,0,10,.1},{c,0,10,.1}]
现在它起作用了。但是如果我想绘制被操纵元素的列表,就像这样
Manipulate[ListPlot[Evaluate[test1]],{a,0,10,.1},{b,0,10,.1},{c,0,10,.1}]
Manipulate[Evaluate[ListPlot[test1]],{a,0,10,.1},{b,0,10,.1},{c,0,10,.1}]
我结束了
在两个追逐中。
我知道 Mathematica 文档中的 'Evaluate Expressions inside Dynamic or Manipulate',但我很确定它没有为我的问题提供解决方案。
最佳答案
所以问题是 test1
是根据全局变量 Global`a
定义的,
但是操作中定义的 a
是由 DynamicModule
创建的,因此是本地的。这就是 acl 在他的 Hold[a]
示例中展示的内容。
也许解决这个问题的最简单方法是使用 With
将 test1
插入到操作中:
Clear[a, b, c]
test1 = {a, b, c};
With[{test1 = test1},
Manipulate[test1, {a, 0, 10, .1}, {b, 0, 10, .1}, {c, 0, 10, .1}]]
这样
Manipulate
永远不会真正看到 test1
,它看到的只是 {a,b,c}
,然后它会继续正确定位。尽管如此,如果在 a,b,c
运行之前给 Manipulate
赋值,这将遇到问题 - 因此是 Clear[a,b,c]
命令。我认为最好的做法是在操作中使所有局部变量完全显式。所以你应该做类似的事情
Clear[a, b, c, test1]
test1[a_, b_, c_] := {a, b, c};
Manipulate[test1[a, b, c], {a, 0, 10, .1}, {b, 0, 10, .1}, {c, 0, 10, .1}]
这避免了您所拥有的全局变量与局部变量的问题。当您必须返回并再次阅读自己的代码时,它还可以让您更轻松。
编辑 以回答评论中的问题“我真的很想了解为什么 Evaluate 不适用于有些嵌套的 ListPlot?”。 IANLS(我不是 Leonid Shifrin ),所以我的大脑中没有一个完美的 Mathematica ( non ) standard 评估序列,但我会尝试解释发生了什么。
好的,与
Plot
不同,ListPlot
不需要本地化任何变量,因此它没有 Attribute
HoldAll
。让我们定义类似于您的示例的内容:
ClearAll[a, test]
test = {a, a + 1};
你给出的最后一个例子 就像
Manipulate[Evaluate[ListPlot[test]], {a, 0, 1}]
通过查看
Trace
,您会看到这首先评估了 ListPlot[test] ~> ListPlot[{a,a+1}]
的第一个参数由于
a
尚未本地化,因此它会生成一个空列表图。要看到这一点,只需运行ListPlot[{a, a + 1}]//InputForm
获取空的图形对象
Graphics[{}, {AspectRatio -> GoldenRatio^(-1), Axes -> True, AxesOrigin -> {0, 0}, PlotRange -> {{0., 0.}, {0., 0.}}, PlotRangeClipping -> True, PlotRangePadding -> {Scaled[0.02], Scaled[0.02]}}]
由于符号值
a
已被丢弃,因此它们无法被 Manipulate
本地化,因此不会发生其他事情。这可以通过仍然评估第一个参数来解决,但在
ListPlot
本地化变量之前不调用 Manipulate
。例如,以下两个工作Manipulate[Evaluate[listPlot[test]], {a, 0, 1}] /. listPlot -> ListPlot
Manipulate[Evaluate[Hold[ListPlot][test]], {a, 0, 1}] // ReleaseHold
ListPlot
丢弃非数字值而没有丝毫提示的事实可能是一个功能,但可能会导致一些令人讨厌的难以跟踪的错误(例如这个问题所涉及的错误)。如果绘图值是非数字的,也许更一致(但不太有用?)的行为是返回未评估的 ListPlot
......或者至少发出警告,指出某些非数字点已被丢弃。你给出的倒数第二个例子 是(更多?)有趣的,它看起来像
Manipulate[ListPlot[Evaluate[test]], {a, 0, 1}]
现在因为
Manipulate
有属性 HoldAll
,它做的第一件事就是将参数包装在 Hold
中,所以如果你查看 Trace
,你会看到 Hold[ListPlot[Evaluate[test]]]
被携带。 Evaluate
没有看到 ,因为如 Possible Issues 部分所述,“评估仅在第一级工作,直接在持有的函数内部”。这意味着 test
直到变量被本地化后才会被评估,因此它们被视为全局 a
而不是本地 ( DynamicModule
) a
。值得考虑以下变体是如何工作的
ClearAll[a, test, f, g]
SetAttributes[g, HoldAll];
test = {a, a + 1};
Grid[{
{Manipulate[test, {a, 0, 1}], Manipulate[Evaluate[test], {a, 0, 1}]},
{Manipulate[f[test], {a, 0, 1}],
Manipulate[f[Evaluate[test]], {a, 0, 1}]},
{Manipulate[g[test], {a, 0, 1}],
Manipulate[g[Evaluate[test]], {a, 0, 1}]}
}]
关于wolfram-mathematica - 对 Manipulate 语句中的表达式求值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7263352/