2013-04-19 25 views
7

Tại sao giá trị fail ném một ngoại lệ? fine giá trị hoạt động. Nếu tôi xóa inline hoặc nếu tôi chuyển đổi 't thành float thì nó hoạt động. nhắnToán tử cộng tuyến trong cấu trúc ném ngoại lệ (F #)

[<Struct>] 
type Test<'t> = 
    val x: 't 
    val y: 't 
    new (x,y) = { x = x; y = y } 

    static member inline (+) ((x,y), a: _ Test) = 0 
    static member inline (-) ((x,y), a: _ Test) = 0 

let a = 1.,2. 
let b = Test(1.,2.) 
let fine = a - b 
let fail = a + b 

lỗi:

Unhandled Exception: System.TypeInitializationException: Loại initializer fo r 'AdditionDynamicImplTable 3' threw an exception. ---> System.NotSupportedExcep tion: Dynamic invocation of op_Addition involving coercions is not supported. at [email protected][a,b,c](Type aty, Type bt y, Unit unitVar0) at Microsoft.FSharp.Core.LanguagePrimitives.AdditionDynamicImplTable 3..cctor () --- End của nội ngoại lệ stack trace - - tại Microsoft.FSharp.Core.LanguagePrimitives.AdditionDynamic [T1, T2, TResult] (T1 x, T2 y) tại. $ Program.main @() trong C: \ Users \ olsv \ Docume nts \ Visual Studio 2012 \ Dự án \ Consol eApplication1 \ ConsoleApplication1 \ Program. fs: dòng 14 Nhấn phím bất kỳ để tiếp tục. . .

Trả lời

5

này trông giống như một lỗi trong trình biên dịch - hay tôi thiếu một cái gì đó (xin vui lòng báo cáo nó tại fsbugs tại microsoft dot com). Đối với một số lý do, trình biên dịch không trực tiếp cuộc gọi đến toán tử + (có vẻ như hoạt động cho -/ và cho các toán tử tùy chỉnh như +., nhưng không thành công cho +*).

Điều này có nghĩa rằng trình biên dịch thực sự tạo ra một cái gì đó như:

// Inlined - returns zero directly 
fine = 0; 

// Failed to inline - calls a version which used dynamic lookup 
fail = LanguagePrimitives.AdditionDynamic 
     <Tuple<double, double>, Test.Test<double>, double>(a, b); 

Phương pháp AdditionDynamic sử dụng một số bảng nội bộ để tìm một thực hiện + cho hai loại tại thời gian chạy. Mặc dù bạn có thể đăng ký loại của bạn ở đó, nó sẽ không thực sự hữu ích, bởi vì lời gọi sẽ chậm.

tôi không thực sự có bất kỳ cách giải quyết tốt đẹp cho này - nếu bạn cần các nhà điều hành chỉ cho một số loại hình cơ bản số (float, int, vv) sau đó lựa chọn dễ dàng nhất có thể để chỉ cần tránh sử dụng inline đây và xác định (một quá tải) điều hành cho các loại cụ thể:

static member (+) ((x:float,y:float), a: float Test) = x + y + a.x + a.y 

Bạn cũng có thể thử các mẹo với nhà điều hành toàn cầu và một loại helper mà thực hiện quá tải khác nhau, nhưng tôi không chắc chắn nếu điều đó sẽ giúp: xem, ví dụ , this past question.