问题描述
对我来说,g/: f[g[x_]] := h[x]
只是冗长的 f[g[x_]] := h[x].你能举一个必须使用
/:
的例子吗?
To me,
g /: f[g[x_]] := h[x]
is just verbose equivalent of f[g[x_]] := h[x]
. Can you raise an example that you have to use /:
?
推荐答案
其实,
g/: f[g[x_]] := h[x]
并不等同于 f[g[x_]] := h[x]
.后者将定义与 f
相关联,而 TagSet
(/:
) 和 UpSet
(^=
及其延迟版本, ^:=
) 将定义与g
.这是一个至关重要的区别,可以通过一个简单的例子来说明.假设您想要一组遵守模 5 加法的变量,即 6 + 7 mod 5 = 3.因此,我们希望任何带有 Head
mod
的东西都能正确运行.最初,我们认为
Actually,
g /: f[g[x_]] := h[x]
is not equivalent to f[g[x_]] := h[x]
. The latter associates the definition with f
, while TagSet
(/:
) and UpSet
(^=
and its delayed version, ^:=
) associate the definition with g
. This is a crucial difference and can be illustrated by a simple example. Let's say you want to have a set of variables that obey modulo 5 addition, i.e. 6 + 7 mod 5 = 3. So, we want anything with Head
mod
to behave correctly. Initially, we'd think that
a_mod + b_mod := mod@Mod[a + b, 5]
会起作用.但是,它会产生错误
would work. But, it generates the error
SetDelayed::write : Tag Plus in a_mod + b_mod is Protected.
我们可以删除
Unprotect
Plus
,然后我们的定义就可以工作了,但这可能会导致其他定义出现问题,并且随着Plus
积累更多的定义,它会变慢.或者,我们可以通过 TagSet
We could remove
Unprotect
Plus
and our definition would then work, but this may cause problems with other definitions and as Plus
accumulates more definitions, it would slow down. Alternatively, we can associate the addition property with the mod
object itself via TagSet
mod /: mod[a_] + mod[b_] := mod @ Mod[a + b, 5]
或
UpSetDelayed
mod[a_] + mod[b_] ^:= mod @ Mod[a + b, 5]
设置 upvalue 有点从概念的角度来看更正确,因为
mod
是具有不同属性的那个.
Setting an upvalue is somewhat more correct from a conceptual point of view since
mod
is the one with the different property.
有几个问题需要注意.首先upvalue机制只能扫描一层,即
Plus[a_mod, b_mod]
没问题,但是Exp[Plus[a_mod, b_mod]]
会报错.这可能需要您使用中间类型获得创意.其次,从编码的角度来看,UpSetDelayed
更容易编写,但有时对于与哪个 Head
相关联的 upvalue 存在一些歧义.TagSet
通过显式命名适当的 Head
来处理这个问题,总的来说,与 UpSet
相比,我更喜欢使用它.
There are a couple of issues to be aware of. First, the upvalue mechanism can only scan one level deep, i.e.
Plus[a_mod, b_mod]
is fine, but Exp[Plus[a_mod, b_mod]]
will throw an error. This may require you to get creative with an intermediate type. Secondly, from a coding perspective UpSetDelayed
is easier to write, but occasionally there is some ambiguity as to which Head
is the upvalue associated with. TagSet
handles that by explicitly naming the appropriate Head
, and in general, it is what I tend to prefer over UpSet
.
Mathematica 的一些运算符没有任何与其相关的行为,因此它们不受保护.对于这些运算符,您可以根据需要定义函数.例如,我定义了
Some of Mathematica's operators do not have any behavior associated with them, so they're not protected. For these operators, you can define functions as you wish. For instance, I've defined
a_ \[CircleTimes] b_ := KroneckerProduct[a,b]
a_ \[CircleTimes] b_ \[CircleTimes] c__ := a \[CircleTimes] ( b \[CircleTimes] c )
和
a_ \[CirclePlus] b__ := BlockDiagonal[{a,b}]
为我经常使用的矩阵运算提供方便的速记符号.
to provide convenient shorthand notations for matrix operations that I use a lot.
我上面的例子有点做作,但有很多次
UpValues
派上了用场.例如,我发现我需要一个符号形式来表示复杂的统一根在乘法和幂运算下表现得很好.
My example above was a little contrived, but there are a number of times
UpValues
have come in handy. For example, I found that I needed a symbolic form for the complex roots of unity that behaved appropriately under multiplication and exponentiation.
示例:一个简单而有用的示例是将
Symbol
标记为 Real:
Example: A straightforward and useful example is marking a
Symbol
as Real:
makeReal[a__Symbol] := (
# /: Element[#, Reals] := True;
# /: Im[#] := 0;
# /: Re[#] := #;
# /: Abs[#] := Sign[#] #;
# /: Arg[#] := Piecewise[{{0, Sign[#] >= 0}, {Pi, Sign[#] < 0}}]
) & /@ List[a]
注意将
TagSet
用作 Element[ a, Reals ] ^:= True
会产生歧义.a
或 Reals
会附加什么规则?此外,如果我们想要一个正实数,我们可以设置 Arg[#]:=0
这允许 Simplify
像预期的那样表现,例如简化[Sqrt[a^2]] == a
.
Note the use of
TagSet
as Element[ a, Reals ] ^:= True
would be ambiguous. What would the rule be attached to a
or Reals
? Also, if we wanted a positive real number, we could set Arg[#]:=0
which allows Simplify
to behave as expected, e.g. Simplify[Sqrt[a^2]] == a
.
这篇关于“升值"是什么意思在 Mathematica 中意味着什么以及何时使用它们?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!