Tại sao không chú thích các tham số chức năng?


28

Để làm cho câu hỏi này có thể trả lời được, hãy giả sử rằng chi phí mơ hồ trong suy nghĩ của một lập trình viên đắt hơn nhiều sau đó thêm một vài lần nhấn phím.

Vì vậy, tại sao tôi lại cho phép các đồng đội của mình thoát khỏi mà không chú thích các tham số chức năng của họ? Lấy đoạn mã sau làm ví dụ về những gì có thể là một đoạn mã phức tạp hơn nhiều:

let foo x y = x + y

Bây giờ, một kiểm tra nhanh về tooltip sẽ cho bạn thấy rằng F # đã xác định bạn có nghĩa là x và y là ints. Nếu đó là những gì bạn dự định, thì tất cả đều tốt. Nhưng tôi không biết nếu đó là những gì bạn dự định. Điều gì nếu bạn đã tạo mã này để nối hai chuỗi với nhau? Hoặc nếu tôi nghĩ bạn có thể muốn tăng gấp đôi thì sao? Hoặc nếu tôi không muốn phải di chuột qua từng tham số chức năng duy nhất để xác định loại của nó thì sao?

Bây giờ lấy điều này làm ví dụ:

let foo x y = "result: " + x + y

Bây giờ F # giả định rằng bạn có thể có ý định nối chuỗi, vì vậy x và y được định nghĩa là chuỗi. Tuy nhiên, vì người nghèo đang duy trì mã của bạn, tôi có thể xem xét điều này và tự hỏi liệu có lẽ bạn đã có ý định thêm x và y (ints) với nhau và sau đó nối kết quả vào chuỗi cho mục đích UI.

Chắc chắn đối với các ví dụ đơn giản như vậy, người ta có thể để nó đi, nhưng tại sao không thực thi chính sách chú thích loại rõ ràng?

let foo (x:string) (y:string) = "result: " + x + y

Có hại gì khi không rõ ràng? Chắc chắn, một lập trình viên có thể chọn sai loại cho những gì họ đang cố gắng làm, nhưng ít nhất tôi biết họ dự định, đó không chỉ là một sự giám sát.

Đây là một câu hỏi nghiêm túc ... Tôi vẫn còn rất mới với F # và đang rạo rực con đường cho công ty của tôi. Các tiêu chuẩn tôi áp dụng có thể sẽ là cơ sở cho tất cả mã hóa F # trong tương lai, được nhúng vào quá trình dán sao chép vô tận mà tôi chắc chắn sẽ thấm vào văn hóa trong nhiều năm tới.

Vậy ... có điều gì đặc biệt về suy luận kiểu của F # khiến nó trở thành một tính năng có giá trị để giữ, chú thích chỉ khi cần thiết? Hay chuyên gia F # -ers tạo thói quen chú thích các tham số của họ cho các ứng dụng không tầm thường?


Phiên bản chú thích là ít chung chung. Đó là vì lý do tương tự, tốt nhất bạn nên sử dụng IEnumerable <> trong chữ ký và không được sắp xếp <>.
Patrick

2
@Patrick - Không, không, vì F # đang suy ra kiểu chuỗi. Tôi đã không thay đổi chữ ký của chức năng, chỉ làm cho nó rõ ràng.
JDB

1
@Patrick - Và ngay cả khi đó là sự thật, bạn có thể giải thích tại sao đó là một điều xấu không? Có lẽ chữ ký nên ít chung chung hơn, nếu đó là những gì lập trình viên đã dự định. Có lẽ chữ ký chung hơn thực sự gây ra vấn đề, nhưng tôi không chắc người lập trình dự định cụ thể như thế nào nếu không có một lượng lớn nghiên cứu.
JDB

1
Tôi nghĩ thật công bằng khi nói rằng, trong các ngôn ngữ chức năng, bạn thích tính tổng quát và chú thích trong trường hợp cụ thể hơn; ví dụ: khi bạn muốn hiệu suất tốt hơn và có thể lấy nó bằng cách sử dụng gợi ý kiểu. Sử dụng các hàm chú thích ở mọi nơi sẽ yêu cầu bạn viết quá tải cho từng loại cụ thể, có thể không được bảo hành trong trường hợp chung.
Robert Harvey

Câu trả lời:


30

Tôi không sử dụng F #, nhưng trong Haskell, nó được coi là hình thức tốt để chú thích (ít nhất) các định nghĩa cấp cao nhất và đôi khi là các định nghĩa cục bộ, mặc dù ngôn ngữ có kiểu suy luận phổ biến. Điều này là vì một vài lý do:

  • Đọc
    Khi bạn muốn biết cách sử dụng một chức năng, thật hữu ích khi có chữ ký loại có sẵn. Bạn có thể chỉ cần đọc nó, thay vì cố gắng tự suy luận hoặc dựa vào các công cụ để làm điều đó cho bạn.

  • Tái cấu trúc
    Khi bạn muốn thay đổi một hàm, việc có một chữ ký rõ ràng cung cấp cho bạn một số đảm bảo rằng các phép biến đổi của bạn giữ nguyên ý định của mã gốc. Trong một ngôn ngữ được suy luận kiểu, bạn có thể thấy rằng mã đa hình cao sẽ đánh máy nhưng không làm những gì bạn dự định. Chữ ký loại là một rào cản trên mạng mà cụ thể hóa thông tin loại tại một giao diện.

  • Hiệu suất
    Trong Haskell, loại chức năng được suy luận có thể bị quá tải (bằng cách đánh máy), có thể ngụ ý một công văn thời gian chạy. Đối với các loại số, loại mặc định là một số nguyên có độ chính xác tùy ý. Nếu bạn không cần tính tổng quát của các tính năng này, thì bạn có thể cải thiện hiệu suất bằng cách chuyên dụng chức năng cho loại cụ thể bạn cần.

Đối với các định nghĩa cục bộ, letbiến liên kết và tham số chính thức cho lambdas, tôi thấy rằng chữ ký loại thường có giá cao hơn mã so với giá trị mà chúng sẽ thêm. Vì vậy, trong đánh giá mã, tôi sẽ đề nghị bạn nhấn mạnh vào chữ ký cho các định nghĩa cấp cao nhất và chỉ yêu cầu các chú thích hợp lý ở nơi khác.


3
Điều này nghe có vẻ như một phản ứng rất hợp lý và cân bằng.
JDB

1
Tôi đồng ý rằng việc định nghĩa với các loại được xác định rõ ràng có thể giúp ích khi tái cấu trúc, nhưng tôi thấy rằng kiểm thử đơn vị cũng có thể giải quyết vấn đề này và vì tôi tin rằng kiểm thử đơn vị nên được sử dụng với lập trình chức năng để đảm bảo chức năng hoạt động như được thiết kế trước khi sử dụng chức năng với một chức năng khác, điều này cho phép tôi loại bỏ các định nghĩa và có sự tự tin rằng nếu tôi thực hiện một thay đổi đột phá thì nó sẽ bị bắt. Ví dụ
Guy Coder

4
Trong Haskell, nó được coi là chính xác để chú thích các chức năng của bạn, nhưng tôi tin rằng F # và OCaml thành ngữ có xu hướng bỏ qua các chú thích trừ khi cần thiết để loại bỏ sự mơ hồ. Điều đó không có nghĩa là nó có hại (mặc dù cú pháp chú thích trong F # là xấu hơn so với trong Haskell).
KChaloux 17/12/13

4
@KChaloux Trong OCaml, đã có loại chú thích trong .mlitệp giao diện ( ) (nếu bạn viết một chú thích mà bạn được khuyến khích. Loại chú thích có xu hướng bị bỏ qua khỏi các định nghĩa vì chúng sẽ bị thừa với giao diện.
Gilles ' SO- đừng trở nên xấu xa '

1
@Gilles @KChaloux thực sự, giống nhau trong .fsicác tệp chữ ký F # , với một cảnh báo: F # không sử dụng các tệp chữ ký để suy luận kiểu, vì vậy nếu có gì đó trong quá trình triển khai không rõ ràng, bạn vẫn sẽ phải chú thích lại. books.google.ca/...
Yawar Amin

1

Jon đã đưa ra một câu trả lời hợp lý mà tôi sẽ không lặp lại ở đây. Tuy nhiên tôi sẽ chỉ cho bạn một tùy chọn có thể đáp ứng nhu cầu của bạn và trong quá trình bạn sẽ thấy một loại câu trả lời khác ngoài câu trả lời có / không.

Gần đây tôi đã làm việc với phân tích cú pháp bằng cách sử dụng các trình kết hợp trình phân tích cú pháp. Nếu bạn biết phân tích cú pháp thì bạn biết bạn thường sử dụng một từ vựng trong giai đoạn đầu tiên và một trình phân tích cú pháp trong giai đoạn thứ hai. Trình lexer chuyển đổi văn bản thành mã thông báo và trình phân tích cú pháp chuyển đổi mã thông báo thành AST. Bây giờ với F # là ngôn ngữ chức năng và bộ kết hợp được thiết kế để kết hợp, bộ kết hợp trình phân tích cú pháp được thiết kế để sử dụng các hàm giống nhau trong cả trình lexer và trình phân tích cú pháp nếu bạn đặt loại cho các hàm kết hợp trình phân tích cú pháp, bạn chỉ có thể sử dụng chúng cho lex hoặc để phân tích và không cả hai.

Ví dụ:

/// Parser that requires a specific item.

// a (tok : 'a) : ('a list -> 'a * 'a list)                     // generic
// a (tok : string) : (string list -> string * string list)     // string
// a (tok : token)  : (token list  -> token  * token list)      // token

hoặc là

/// Parses iterated left-associated binary operator.


// leftbin (prs : 'a -> 'b * 'c) (sep : 'c -> 'd * 'a) (cons : 'd -> 'b -> 'b -> 'b) (err : string) : ('a -> 'b * 'c)                                                                                    // generic
// leftbin (prs : string list -> string * string list) (sep : string list -> string * string list) (cons : string -> string -> string -> string) (err : string) : (string list -> string * string list)  // string
// leftbin (prs : token list  -> token  * token list)  (sep : token list  -> token  * token list)  (cons : token  -> token  -> token  -> token)  (err : string) : (token list  -> token  * token list)   // token

Vì mã là bản quyền, tôi sẽ không bao gồm nó ở đây nhưng nó có sẵn tại Github . Đừng sao chép nó ở đây.

Để các chức năng hoạt động, chúng phải được để lại với các tham số chung, nhưng tôi bao gồm các nhận xét hiển thị các loại được suy luận tùy thuộc vào các chức năng sử dụng. Điều này giúp dễ dàng hiểu chức năng để bảo trì trong khi để lại chức năng chung để sử dụng.


1
Tại sao bạn không viết phiên bản chung vào hàm? Điều đó có hiệu quả không?
Svick

@svick Tôi không hiểu câu hỏi của bạn. Bạn có nghĩa là tôi đã loại các loại ra khỏi định nghĩa hàm, nhưng có thể đã thêm các loại chung vào các định nghĩa hàm vì các loại chung sẽ không thay đổi ý nghĩa của hàm? Nếu vậy lý do là nhiều hơn một sở thích cá nhân. Khi tôi lần đầu tiên bắt đầu với F # tôi đã thêm chúng. Khi tôi bắt đầu làm việc với những người dùng cao cấp hơn của F #, họ thích họ được để lại dưới dạng nhận xét vì việc sửa đổi mã dễ dàng hơn mà không cần chữ ký ở đó. ...
Guy Coder

Về lâu dài, cách tôi thể hiện chúng là các bình luận hoạt động cho mọi người một khi mã đang hoạt động. Khi tôi bắt đầu viết một chức năng, tôi đặt các loại. Khi tôi có chức năng hoạt động, tôi chuyển chữ ký loại sang một nhận xét và xóa càng nhiều loại càng tốt. Đôi khi với F #, bạn cần để lại loại để giúp suy luận. Trong một thời gian, tôi đã thử nghiệm tạo bình luận bằng let và = để bạn có thể bỏ dòng thử nghiệm, sau đó bình luận lại khi hoàn thành, nhưng chúng trông thật ngớ ngẩn và thêm let và = không khó lắm.
Guy Coder

Nếu những bình luận này trả lời những gì bạn đang hỏi hãy cho tôi biết để tôi có thể chuyển chúng vào câu trả lời.
Guy Coder

2
Vì vậy, khi bạn sửa đổi mã, bạn không sửa đổi các bình luận, dẫn đến tài liệu lỗi thời? Điều đó không giống như một lợi thế đối với tôi. Và tôi không thực sự thấy bình luận lộn xộn như thế nào tốt hơn mã lộn xộn. Đối với tôi, có vẻ như phương pháp này kết hợp những nhược điểm của hai lựa chọn.
Svick 17/12/13

-8

Số lượng lỗi tỷ lệ thuận với số lượng ký tự trong một chương trình!

Điều này thường được nêu là số lượng lỗi tỷ lệ thuận với các dòng mã. Nhưng có ít dòng hơn với cùng một lượng mã sẽ cho cùng một lượng lỗi.

Vì vậy, trong khi thật tuyệt khi được rõ ràng, bất kỳ tham số bổ sung nào bạn nhập có thể dẫn đến lỗi.


5
Số lượng lỗi tỷ lệ thuận với số lượng ký tự trong một chương trình! Vì vậy, tất cả chúng ta nên chuyển sang APL ? Quá ngắn gọn là một vấn đề, giống như quá dài dòng.
Svick

5
" Để làm cho câu hỏi này có thể trả lời được, hãy giả sử rằng chi phí mơ hồ trong suy nghĩ của một lập trình viên đắt hơn nhiều sau đó thêm một vài lần nhấn phím. "
JDB 17/12/13
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.