ReplaceAll 未按预期工作
Mathematica 还处于早期阶段,所以请原谅这个可能是一个非常明显的问题。我正在尝试生成一些参数图。我有:
ParametricPlot[{
(a + b) Cos[t] - h Cos[(a + b)/b t],
(a + b) Sin[t] - h Sin[(a + b)/b t]},
{t, 0, 2 \[Pi]}, PlotRange -> All] /. {a -> 2, b -> 1, h -> 1}
不高兴:不应用替换规则,并且 a
、b
和 h
保持未定义。
如果我这样做:
Hold@ParametricPlot[{
(a + b) Cos[t] - h Cos[(a + b)/b t],
(a + b) Sin[t] - h Sin[(a + b)/b t]},
{t, 0, 2 \[Pi]}, PlotRange -> All] /. {a -> 2, b -> 1, h -> 1}
看起来规则正在发挥作用,正如输出所证实的那样:
Hold[ParametricPlot[{(2 + 1) Cos[t] -
1 Cos[(2 + 1) t], (2 + 1) Sin[t] - 1 Sin[(2 + 1) t]}, {t, 0,
2 \[Pi]}, PlotRange -> All]]
这就是我所期望的。不过,如果取消 Hold
,ParametricPlot
就不起作用。不过,方程或 ParametricPlot 本身没有任何问题,因为我尝试在单独的表达式中设置 a、b 和 h 的值 (a=2; b=1; h=1
),我按预期得到了漂亮的双心形。
那么,我在 ReplaceAll
上做错了什么,为什么转换规则不起作用?这是 MMA 的另一个根本性重要方面,但我的 OOP 毁掉的大脑无法理解。
我尝试阅读 ReplaceAll
和 ParametricPlot
,我发现的最接近的线索是“ParametricPlot
具有属性 HoldAll
并且仅在将特定数值分配给变量后才计算 f
”,这没有多大帮助,否则我就不会在这里。
谢谢。
Still early days with Mathematica so please forgive what is probably a very obvious question. I am trying to generate some parametric plots. I have:
ParametricPlot[{
(a + b) Cos[t] - h Cos[(a + b)/b t],
(a + b) Sin[t] - h Sin[(a + b)/b t]},
{t, 0, 2 \[Pi]}, PlotRange -> All] /. {a -> 2, b -> 1, h -> 1}
No joy: the replacement rules are not applied and a
, b
and h
remain undefined.
If I instead do:
Hold@ParametricPlot[{
(a + b) Cos[t] - h Cos[(a + b)/b t],
(a + b) Sin[t] - h Sin[(a + b)/b t]},
{t, 0, 2 \[Pi]}, PlotRange -> All] /. {a -> 2, b -> 1, h -> 1}
it looks like the rules ARE working, as confirmed by the output:
Hold[ParametricPlot[{(2 + 1) Cos[t] -
1 Cos[(2 + 1) t], (2 + 1) Sin[t] - 1 Sin[(2 + 1) t]}, {t, 0,
2 \[Pi]}, PlotRange -> All]]
Which is what I'd expect. Take the Hold
off, though, and the ParametricPlot
doesn't work. There's nothing wrong with the equations or the ParametricPlot
itself, though, because I tried setting values for a, b and h in a separate expression (a=2; b=1; h=1
) and I get my pretty double cardoid out as expected.
So, what am I doing wrong with ReplaceAll
and why are the transformation rules not working? This is another fundamentally important aspect of MMA that my OOP-ruined brain isn't understanding.
I tried reading up on ReplaceAll
and ParametricPlot
and the closest clue I found was that "ParametricPlot
has attribute HoldAll
and evaluates f
only after assigning specific numerical values to variables" which didn't help much or I wouldn't be here.
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Mathematica 通过首先评估每个子表达式的头来评估每个头而不保留属性。由于 ReplaceAll 没有保持属性,因此在替换之前
ParametricPlot
变为Graphics
要查看表达式树,请执行
相同
从该树中您可以看到您的命令与执行Look 在
FullForm[temp1]
中确认该表达式中没有a
或b
。如果您将
ReplaceAll
设置为HoldFirst
,则会阻止 ParametricPlot 在ReplaceAll
之前进行计算,结果就是您所期望的。在本例中,ReplaceAll
计算结果为带有头ParametricPlot
的表达式,并且仅在该点计算ParametricPlot
。确保重置属性,因为更改内置命令的行为可能会产生意外的副作用。当需要使用
HoldAll
评估传递给函数的参数时,一个有用的技巧是对具有List
头的表达式进行操作,并在结束,例如Mathematica evaluates each head without holding attributes by first evaluating head of each subexpression. Since ReplaceAll doesn't have holding attributes,
ParametricPlot
becomesGraphics
before replacementTo see the expression tree, do
From that tree you can see that your command is the same as doing
Look at
FullForm[temp1]
to confirm that there's noa
orb
in that expression.If you set
ReplaceAll
toHoldFirst
, that prevents ParametricPlot from being evaluated beforeReplaceAll
, and result is what you expected. In this case,ReplaceAll
evaluates to expression with headParametricPlot
, and only at that pointParametricPlot
is evaluated. Make sure to reset the attributes back because changing behavior of built-in commands can have unexpected side-effects.A useful trick when needing to evaluate arguments passed to function with
HoldAll
is to do operations on an expression withList
head, and substituteParametricPlot
in the end, for instance在 Mathematica 中使用局部变量的最佳方法是
Module[]
:这样 a、b 和 h 不会在全局上下文中获得指定值,而只能在
Module
内部获得指定值。如果您仍然想使用替换规则,则只需在完成替换后ReleaseHold
:编辑:至于为什么会发生这种情况。按照我的理解,
HoldAll
可以防止函数的参数被任何规则(内部或显式)修改。您的Hold
的作用是将整个函数(不仅仅是参数)置于保留状态,并且在函数经过评估(它没有执行)之后应用替换规则。所以仍然有一些东西需要替换)并且HoldAll
不再有效。当然,
Hold
也有HoldAll
作为属性,所以这并不能解释为什么ParametricPlot
的HoldAll
是不同的。 :-(EDIT2: 我使用
Trace
来查看发生的情况,似乎ReplaceAll
仅在最后应用,当 < code>ParametricPlot 已经变成图形对象(并且不再包含 a、b 或 h)。保留的计算结果为Hold[a]
,然后可以成功应用替换规则。The best way for using local variables in Mathematica is
Module[]
:This way a, b, and h do not get assigned values in the Global context but only inside the
Module
. If you still want to use replacement rules you just have toReleaseHold
after you have done the replacement:EDIT: As to why this happens. The way I understand it,
HoldAll
prevents the arguments of the function from being modified by any rules (internal or explicit). What yourHold
does, is place the entire function on hold (not just the arguments), and the replacement rule gets applied after the function has gone through evaluation (which it didn't so there is still something there to replace) andHoldAll
is no longer valid.Of course,
Hold
also hasHoldAll
as an attribute, so this doen't explain whyParametricPlot
'sHoldAll
is different. :-(EDIT2: I used
Trace
to look at what happens, and it seems likeReplaceAll
gets applied only at the very end, whenParametricPlot
has already turned into a graphical object (and does not contain a, b, or h anymore). In the case ofHold[a] /. a -> 5
the hold evaluates toHold[a]
and the replacement rule can then be successfully applied.这就是 ReplaceAll 始终工作的方式。
请参见示例:
显然,替换是在评估之后完成的,因为如果您这样做:
现在,只需在您希望其操作的级别插入替换即可。由于绘图的结果基本上是一个数字坐标已“解决”的图像,因此您需要在计算绘图之前放入这些坐标。在您的情况下:
That is the way ReplaceAll always work.
See for example:
Clearly the replacement is done AFTER the evaluation, because if you do:
Now, is a matter of inserting the replacement at the level you want it to operate. As the result of a Plot is basically an Image with the numeric coordinates already "solved", you want to put those coordinates in before the plot is calculated. In your case:
这不是一个答案,只是对使用 Module with Plot 的评论。
如果我按如下方式进行,则
以下内容不起作用
方法 1:
方法 2:
以下内容确实有效(方法 3)
,与上述方法(方法 4)一样有效
任何人都可以解释为什么方法 4 有效,但方法 2 无效? (这同样适用于 With,我发现它对 Module 来说更直观)。
就其价值而言,我将使用替换规则生成原始参数图,如下所示:
编辑
方法 1(编辑)不起作用(因为“绘图”将变量 x 视为局部变量,有效地使用“块”?)
在我看来任何人,甚至是那些对 Mathematica 有基本了解的人,都绝对清楚方法 2 发生了什么,显示了 Mathematica 的强大功能和易用性。当方程变得更加复杂时,单独定义它们是否有利?现在还不清楚是否必须使用方法 3 来代替方法 1。(当然,方法 4 可能是最好的。)
This is not an answer as such, just a comment on using Module with Plot.
If I proceed as follows
The following will NOT work
Method 1:
Method 2:
The following does work (Method 3)
as does the method described above (method 4)
Can anyone explain why method 4 works but method 2 doesn't? (The same applies to With, which I find more intuitive to Module).
For what its worth, I would generate the original parametric plot using replacement rules as follows:
EDIT
Method 1 (of Edit) does not work (because 'Plot' treats the variable x as local, effectively using Block'?)
It seems to me that it is absolutely clear to anyone, even those with a rudimentary knowledge of Mathematica, what is going on with Method 2, showing the power and ease-of-use of Mathematica. When the equations become more complex, is it advantageous to define them separately. It is now not so clear that Method 3 must be used instead of Method 1. (Method 4, of course, is probably the best of all.)