我正在将我的矢量标准化为这个函数:
member this.Normalize =
if this.Length > _zerotolerance then
let inv:float = 1.0 / this.Length
this.x <- this.x *= inv // overloaded
this.y <- this.y *= inv // overloaded
然而 - 默认情况下,我没有乘法赋值运算符* = for浮点数,所以我需要创建一个。
根据MSDN http://msdn.microsoft.com/en-us/library/dd233204%28v=vs.110%29,我必须以下列方式重载运算符:
static member ( *= ) (arg1 : type, arg1: type) = ...code etc...
所以我在我的F#代码文件中重载了以下运算符以进行乘法赋值,如下所示:
// Operator
static member ( *= ) ( v1:vector2, v2:vector2 ) =
v1.x <- v1.x + v1.x * v2.x
v1.y <- v1.y + v1.y * v2.y
static member ( *= ) ( v1:vector2, v2:float ) =
v1.x <- v1.x + v1.x * v2
v1.y <- v1.y + v1.y * v2
// Operator
static member ( *= ) ( f1:float, f2:float ) =
f1 <- f1 + f1 * f2
它似乎不起作用。即使在运算符超载后我也遇到以下问题:
vector2.fs(107,36):错误FS0001:类型'float'不支持 任何名为'* ='
的运算符
因此运算符* =不适用于浮点数。它失败了(规范化功能):
this.X <- this.X *= inv
要检查运算符的其他重载,我暂时为Vector2s创建了测试函数:
member this.MultiplyAssignmentTest_1(v1:vector2,v2:vector2):vector2 = v1 *= v2
member this.MultiplyAssignmentTest_2(v1:vector2,v2:float):vector2 = v1 *= v2
操作员通过测试 Vector * = Vector 和 Vector * = Float ,但是当我尝试 Float * = Float时继续失败
第三个测试函数 - float * = float :完全失败并出现完全相同的错误。
member this.MultiplyAssignmentTest_3(v1:float,v2:float):float = v1 *= v2
OFC我总是可以写this.X <- This.X + This.X *= inv
,这对于短公式来说很好。但是当我开始用这个来编写大量的向量数据时,这并不是非常经济的 - 并且为了快速编写代码。
我搞砸了什么?我是不是真的搞砸了我的超载,或者是否有一些我不知道的错误?
为什么它适用于我的 Vector2 * = Float ,而不适用于 Float * = Float ?
或者可能是我自己没有注意到的错字/套管错误?
答案 0 :(得分:2)
正如John所说,最好避免使用mutable。 另一个问题是你想重载float的运算符(* =),但你没有float类型的定义,所以你试图在类的定义中执行它,并且该重载永远不会执行,因为没有参数是类的类型(vector2)。
其他两个重载工作正常,因为重载中涉及的至少一个参数属于类型(vector2),因此它们将解析。
您可以在全局级别定义(= *)但是它不适用于vector2,因此您需要在其定义中在全局级别指定所有重载。
您可以尝试使用独立类进行重载的代码:
type vector2 = {x:float; y:float} with
// Operator
static member ( *= ) ( v1:vector2, v2:vector2 ) =
{x = v1.x + v1.x * v2.x; y = v1.y + v1.y * v2.y }
static member ( *= ) ( v1:vector2, v2:float ) =
{x = v1.x + v1.x * v2; y = v1.y + v1.y * v2 }
type Overloads = Overloads with
static member (?<-) (a:vector2, Overloads, b:vector2) = a *= b
static member (?<-) (a:vector2, Overloads, b:float) = a *= b
static member (?<-) (a:float , Overloads, b:float) = a * b
let inline ( *= ) f1 f2 = f1 ? (Overloads) <- f2
// now you can add more methods for vector2 using the global definition of ( *=)
type vector2 with
static member Length (v1:vector2) = sqrt( v1.x ** 2.0 + v1.y ** 2.0)
// more methods
执行此技巧,您可以对浮点数和vector2使用(* =)。 还要注意,我删除了mutables。
答案 1 :(得分:2)
这也有效:
let inline ( *= ) (p : byref<_>) x = p <- p * x
[<Literal>]
let _zerotolerance = 1e-3
type A(x0, y0) =
let mutable x = x0
let mutable y = y0
member __.Length = sqrt (x * x + y * y)
member this.Normalize =
if this.Length > _zerotolerance then
let inv:float = 1.0 / this.Length
&x *= inv
&y *= inv