2017-02-15 20 views
11

Vì vậy, tôi đang cố gắng tìm hiểu F # và khi tôi học những điều mới, tôi thích nhìn vào IL để xem những gì đang xảy ra dưới bìa. Gần đây tôi đã đọc về Currying, một nền tảng cơ bản của ngôn ngữ.Tại sao không F # biên dịch Currying thành các chức năng riêng biệt?

Theo F# for fun and Profit khi bạn tạo các chức năng dưới đây:

let addItems x y = x + y 

gì đang thực sự xảy ra là có hai chức năng đối số duy nhất được tạo ra.

let addItems x = 
    let subFunction y = 
      x + y 
    subFunction 

và khi bạn gọi hàm với addItems 5 6 thứ tự của các hoạt động như sau

  1. addItems được gọi với tham số 5

  2. addItems trả subfunction

  3. subfunction được gọi với đối số 6
  4. subFunction có đối số 5 trong phạm vi s o nó thêm và trả về tổng của 5 và 6

Tất cả điều này nghe có vẻ tốt trên bề mặt. Tuy nhiên, khi bạn nhìn vào IL cho điều này, nó kể một câu chuyện khác.

.method public static int32 testCurry(int32 x, 
             int32 y) cil managed 
{ 
    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = (01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00) 
    // Code size  5 (0x5) 
    .maxstack 8 
    IL_0000: nop 
    IL_0001: ldarg.0 
    IL_0002: ldarg.1 
    IL_0003: add 
    IL_0004: ret 
} // end of method Sandbox::testCurry 

Chúng ta có thể thấy rõ ràng trong IL rằng một hàm tĩnh duy nhất lấy hai đối số và trả về Int32 được tạo.

Vì vậy, câu hỏi của tôi là, tại sao sự khác biệt? Đây không phải là lần đầu tiên tôi nhìn thấy IL mà không jive với các tài liệu hướng dẫn hoặc là ...

Trả lời

18

Vì vậy, câu hỏi của tôi là, tại sao sự khác biệt?

IL được biên dịch thực tế không cần và thực sự không nên là vấn đề về hợp đồng hành vi. Bằng cách biên dịch thành một hàm duy nhất, một cuộc gọi được tối ưu hóa tốt hơn đáng kể ở mức JIT/runtime.

"Điều gì thực sự xảy ra ở đây ..." không nhất thiết là những gì đang thực sự xảy ra, đó là "làm thế nào điều này nên được lý luận khi viết và sử dụng mã F # là ...". Việc triển khai cơ bản sẽ được tự do thay đổi khi cần thiết, để sử dụng tốt nhất môi trường thời gian chạy.

+0

Tôi đồng ý rằng nó cần được tối ưu hóa càng nhiều càng tốt. Tuy nhiên, khi bạn nói với tôi một điều và một cái gì đó khác đang xảy ra, không phải điều này để lại một cơ hội khổng lồ cho các vấn đề hiệu suất, hoặc khó tìm lỗi, trong cơ sở mã lớn? –

+7

@AnthonyRussell Bạn được cho biết về hợp đồng hành vi - không thể thay đổi. Nếu trình biên dịch gây ra lỗi do một hành vi khác, đó là lỗi trình biên dịch (và phải được sửa). Những thứ tương tự xảy ra trong hầu hết các ngôn ngữ biên dịch (tất cả các ngôn ngữ biên dịch) - trình biên dịch thường sẽ viết lại rất nhiều mã theo cách "tốt hơn" nhưng vẫn giữ nguyên các đặc tính sử dụng và hành vi thời gian chạy tương tự. –

+0

Được rồi, tất cả đều công bằng. Cảm ơn đã phản ứng nhanh chóng! –

Các vấn đề liên quan