2010-12-10 5 views
11

Với F #, tôi hiểu rằng bạn có thể sử dụng từ khóa nội tuyến để thực hiện loại chuyên môn tại trang cuộc gọi. Đó là ::F # inline hoạt động như thế nào?

val inline (+) : ^a -> ^b -> ^c 
     when (^a or ^b) : (static member (+) : ^a * ^b -> ^c) 

ép mà ^a hoặc ^b phải có một thành viên tĩnh như op_Addition, hoặc một trong các xây dựng trong nguyên thủy, có thể được sử dụng để điền vào chỗ trống. Vì vậy, nếu bạn có một phương thức có dấu + và bạn chuyển vào một int và ngắn như các tham số nó unwraps + với một lệnh để sử dụng nguyên thủy được tích hợp cho int, và nếu bạn truyền vào một float và một byte nó sử dụng opcode bổ sung float nguyên thủy.

Làm thế nào chính xác điều này được thực hiện tại thời gian biên dịch? Làm thế nào bạn có thể có một phương pháp trong CLR mà chuyển đổi những gì opcode hoặc phương pháp nó sử dụng dựa trên loại?

Hành vi này có thể xảy ra với Reflection.Emit không? Tôi hiểu rằng nội tuyến được thực hiện tại trang web cuộc gọi, điều đó có nghĩa là mã không hoạt động với C#?

+0

Tôi thực sự không biết nhiều về nội bộ, nhưng có vẻ như mã nguồn F # xác định toán tử '+' (C: \ Program Files (x86) \ FSharp-2.0.0.0 \ source \ fsharp \ FSharp .Core \ prim-types.fs line 3527) chuyển đổi trên các kiểu đối số ở dạng biên dịch và phát ra mã IL trực tiếp. – Juliet

Trả lời

8

Theo đề xuất của inline, mã được gạch chân tại trang web cuộc gọi. Tại mỗi trang gọi, bạn biết tham số kiểu cụ thể ^T, vì vậy mã cụ thể cho loại đó được chèn vào đó.

Điều này được thực hiện bởi trình biên dịch F #, bạn không thể dễ dàng làm điều đó trong ngữ cảnh khác (như C# hoặc Ref.Emit).

Thư viện F # có một số hàm nội tuyến vẫn có thể được gọi bằng các ngôn ngữ khác, thời gian chạy cho các triển khai đó thực hiện điều động dựa trên loại thời gian chạy, xem ví dụ: mã cho AdditionDynamic trong prim-types.fs trong mã F # Core library để có cảm nhận.

+0

Vì vậy, bạn đang nói về cơ bản một thủ thuật biên dịch phức tạp? Nếu tôi gọi một 'FSharpFunc <,>' từ C# tôi có nhận được hành vi mong muốn không? –

+2

Bất kỳ trường hợp nào của loại 'FSharpFunc' (hoặc thực sự hầu hết các loại) không phải là (và không thể) là' nội tuyến'. 'inline' áp dụng cho các phương thức và hàm, và chỉ một số ít chúng trong thư viện F #. Hầu hết các công cụ có thể được gọi là tốt từ C#, nhưng một vài hàm F # 'inline' không hỗ trợ lời gọi động (như' sin') chỉ có thể được gọi từ F #, vì trình biên dịch F # phải nội tuyến mã tại trang gọi. – Brian