我在让 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] 示例中展示的内容。

也许解决这个问题的最简单方法是使用 Withtest1 插入到操作中:

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/

10-12 21:35