1

我正在像这个函数一样规范化我的向量:

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

但是 -默认情况下,我无法使用用于浮点数的乘法赋值运算符 *=,因此我需要创建一个。

根据 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:“浮点”类型不支持任何名为“*=”的运算符

所以运算符 *= 不适用于浮点数。它在这里失败(规范化功能):

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 *= VectorVector *= Float的测试, 但是当我尝试执行Float *= Float时仍然失败

第三个测试函数 - float *= float:完全失败并出现完全相同的错误。

member this.MultiplyAssignmentTest_3(v1:float,v2:float):float = v1 *= v2

OFC 我总是可以写this.X <- This.X + This.X *= inv,这对于简短的公式来说很好。但是当我开始用它编写大量向量数学时,这并不是很经济——而且为了快速编码。

  1. 我搞砸了什么?我真的以某种方式搞砸了我的超载,还是有一个我不知道的错误?

  2. 为什么它适用于我的Vector2 *= Float 但不适用于Float *= Float

  3. 或者我自己没有注意到一个错字/大小写错误?

4

2 回答 2

2

正如约翰所说,最好避免使用可变变量。另一个问题是你想为浮点重载运算符(*=),但你没有浮点类型的定义,所以你试图在你的类的定义中这样做,并且重载将永远不会执行,因为没有参数属于类 (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使用(*=)。另请注意,我删除了可变变量。

于 2012-06-22T07:58:45.357 回答
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
于 2012-06-22T10:56:07.640 回答