对我来说,g /: f[g[x_]] := h[x]
只是详细等效于 f[g[x_]] := h[x]
.你能举一个例子,你必须使用/:
?
最佳答案
其实,g /: f[g[x_]] := h[x]
不等于 f[g[x_]] := h[x]
.后者将定义与 f
相关联。 , 而 TagSet
( /:
) 和 UpSet
( ^=
及其 delayed version , ^:=
) 将定义与 g
相关联.这是一个至关重要的区别,可以通过一个简单的例子来说明。假设您想要一组遵守模 5 加法的变量,即 6 + 7 mod 5 = 3。所以,我们想要任何带有 Head
的变量。 mod
行为正确。最初,我们会认为
a_mod + b_mod := mod@Mod[a + b, 5]
会工作。但是,它会产生错误
SetDelayed::write : Tag Plus in a_mod + b_mod is Protected.
我们可以删除
Unprotect
Plus
然后我们的定义会起作用,但这可能会导致其他定义出现问题,如 Plus
积累更多的定义,它会变慢。或者,我们可以将加法属性与 mod
相关联。对象本身通过 TagSet
mod /: mod[a_] + mod[b_] := mod @ Mod[a + b, 5]
或
UpSetDelayed
mod[a_] + mod[b_] ^:= mod @ Mod[a + b, 5]
设置 upvalue自
mod
以来,从概念的角度来看更正确是具有不同属性的那个。有几个问题需要注意。首先,upvalue机制只能扫描一层深度,即
Plus[a_mod, b_mod]
很好,但是 Exp[Plus[a_mod, b_mod]]
会抛出错误。这可能需要您使用中间类型获得创意。其次,从编码的角度UpSetDelayed
更容易写,但偶尔会有一些含糊不清的地方 Head
是与相关联的升值。 TagSet
通过显式命名适当的 Head
来处理这个问题。 ,一般来说,这是我更喜欢的而不是 UpSet
.Mathematica 的一些运算符没有任何与之相关的行为,因此它们不 protected 。对于这些运算符,您可以根据需要定义函数。例如,我已经定义
a_ \[CircleTimes] b_ := KroneckerProduct[a,b]
a_ \[CircleTimes] b_ \[CircleTimes] c__ := a \[CircleTimes] ( b \[CircleTimes] c )
和
a_ \[CirclePlus] b__ := BlockDiagonal[{a,b}]
为我经常使用的矩阵运算提供方便的速记符号。
我上面的例子有点做作,但有很多次
UpValues
已经派上用场了。例如,我发现我需要一个符号形式来表示复杂的统一根在乘法和幂运算下表现得很好。示例 :一个简单而有用的例子是标记
Symbol
作为真实: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
按预期行事,例如Simplify[Sqrt[a^2]] == a
.
关于wolfram-mathematica - "upvalue"在 Mathematica 中是什么意思以及何时使用它们?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6648260/