在Mathematica中定义控制变量

7

当我使用 Manipulate 时,我可以做到:

Manipulate[x, {u, 1, 10}]

实际上,我的控件很多且复杂,因此我更喜欢将它们的定义从Manipulate表达式中分离出来,像这样:

control = {u, 1, 10}
Manipulate[x, control]

但这会导致一个错误:
Manipulate argument control does not have the correct form for a \
variable specification.

为什么它不能那样工作呢?

1
你提供的例子,以及我在大多数答案中看到的情况是,代码的复杂性根本没有减少。一些答案使用了更多的字符、一堆额外的作用域结构等,创建了非常复杂的代码。我认为,在大多数情况下,只需改善代码的布局(每个控件占据一行,视觉上将相关控件分组等)就足够了。 - Sjoerd C. de Vries
通过参考答案,我更好地理解了正在发生的事情,但您完全正确:没有任何构造使代码真正简单。让我感到疯狂的是我的代码中嵌套深度令人难以置信。也许这就是Lisp的做法,但是有没有一种方法可以使我的程序更线性? - Ludwig Weinzierl
1
@Sjoerd 嗯,如果一段代码只出现在一个地方,那么我基本上同意你的看法。如果要在多个地方使用该代码,或者完整的代码过长,难以轻松修改,那么这样做通常是有意义的。例如,我有一个笔记本,其中包含的 Manipulate 代码在我的 MacBook 的 13 英寸屏幕上无法正常显示。我要么使用这种技巧,要么每次需要修改时都要尝试将整个代码放在脑海中。由于我已经必须认真思考我实际解决的问题,因此我宁愿通过添加一些字符来减少代码复杂性。 - acl
@Sjoerd是正确的,布局可以帮助。如果您在其中放置显式回车符,Mma笔记本可以很好地缩进行。虽然acl和我回答了您最初的问题,但我认为简化大型操作的更好方法是将控件保留在其中,但将其他所有内容移出。例如,请参见S M Blinder的演示文稿-例如牛顿摆 - Simon
2个回答

11

Manipulate具有HoldAll属性。您可以强制control进行评估并且一切正常工作。

control = {u, 1, 10};
Manipulate[x[u], Evaluate[control]]

这样做的问题在于变量u没有被适当地本地化,因此如果您已经在其他地方设置了u=1,那么Manipulate将返回错误。根据您要做的具体情况,最好使用适当的作用域构造,例如WithDynamicModule。这可能有些过度,但它确保了u是本地的,并将control移出了操纵。
DynamicModule[{u}, With[{control = {u, 1, 10}}, Manipulate[x[u], control]]]

10

这个

con = {u, 1, 10};
Manipulate[
 u,
 Evaluate@con
 ]

这段代码是有效的。 我认为如果没有Evaluate,它将无法正常工作,因为


Attributes[Manipulate]

这表明Manipulate具有属性 HoldAll(但我可能是错的)。要查看此属性的影响,请尝试执行以下操作:

SetAttributes[f, HoldAll]
f[con]
f[Evaluate@con]
g[con]
(*
f[con]
f[{u, 1, 10}]
g[{u, 1, 10}]
*)
因此,由于HoldAll属性的存在,Manipulate似乎根本看不到con中的内容,除非您明确地对其进行评估。

1
你比我赢了那么多!所以,+1。 - Simon
@Simon 谢谢!我也给你点赞。猜想我最终可能会得到更少的赞 :) - acl
谢谢,当我将您的示例复制并粘贴到新工作表中时,它可以正常工作。但在我的旧工作表中,即使是控制={u,1,10}这一行没有改变,我也必须在每一行上按Shift+Enter才能使其正常工作。为什么我需要重新评估这些行呢? - Ludwig Weinzierl
@Ludwig 我不知道。听起来像是行尾字符的问题,但谁知道呢...它们最终是否分别出现在单元格中?(您可以通过mma窗口右侧的单元格括号来判断) - acl
@acli:我无法重现错误,现在它按预期工作,谢谢。 - Ludwig Weinzierl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接