Tại sao Scala yêu cầu các hàm phải có kiểu trả về rõ ràng?


11

Gần đây tôi đã bắt đầu học lập trình ở Scala và cho đến nay nó vẫn rất vui. Tôi thực sự thích khả năng khai báo các chức năng trong một chức năng khác mà dường như là điều trực quan cần làm.

Một điều thú vị tôi có về Scala là Scala yêu cầu kiểu trả về rõ ràng trong các chức năng của nó . Và tôi cảm thấy như điều này cản trở tính biểu cảm của ngôn ngữ. Ngoài ra, thật khó để lập trình với yêu cầu đó. Có lẽ đó là vì tôi đến từ vùng thoải mái Javascript và Ruby. Nhưng đối với một ngôn ngữ như Scala sẽ có vô số chức năng được kết nối trong một ứng dụng, tôi không thể hình dung được cách tôi động não trong đầu chính xác loại chức năng cụ thể mà tôi đang viết nên quay lại với các lần truy cập sau khi thu hồi.

Yêu cầu khai báo kiểu trả về rõ ràng này trên các hàm, đừng làm phiền tôi đối với các ngôn ngữ như Java và C ++. Các cuộc truy tìm trong Java và C ++, khi chúng đã xảy ra, thường được xử lý tối đa 2 đến 3 hàm. Không bao giờ một số chức năng kết nối với nhau như Scala.

Vì vậy, tôi đoán tôi đang tự hỏi nếu có một lý do chính đáng tại sao Scala nên có yêu cầu của các hàm có kiểu trả về rõ ràng?


5
Nó không - và tôi không biết tại sao nó sẽ là một vấn đề nếu nó xảy ra.
Keith Thompson

1
Tôi nghĩ rằng nó đã làm. Có trường hợp nào trong Scala mà kiểu trả về cho một hàm thực sự không rõ ràng không?
thu gom rác

Câu trả lời:


15

Scala không yêu cầu loại trả về rõ ràng trên tất cả các hàm, chỉ cần các kiểu đệ quy. Lý do cho điều đó là thuật toán suy luận kiểu của Scala là (một cái gì đó gần với) một lần quét đơn giản từ đầu đến cuối không có khả năng nhìn.

Điều này có nghĩa là một chức năng như thế này:

def fortuneCookieJoke(message: String) = message + " in bed."

không cần loại trả về, vì trình biên dịch Scala có thể thấy rõ, mà không cần sử dụng các biến logic hoặc nhìn vào bất cứ thứ gì ngoài các tham số của phương thức, loại trả về phải là String.

Mặt khác, một chức năng như thế này:

def mapInts(f: (Int) => Int, l: List[Int]) = l match {
  case Nil => Nil
  case x :: xs => f(x) :: mapInts(f, xs)
}

sẽ gây ra lỗi thời gian biên dịch, bởi vì trình biên dịch Scala không thể nhìn thấy, mà không sử dụng các biến logic hoặc biến logic, chính xác kiểu của mapIntsnó là gì. Điều nhiều nhất có thể nói, nếu nó đủ thông minh, thì kiểu trả về là một siêu kiểu List[Nothing], vì Nilnó thuộc loại đó. Điều đó không cung cấp cho nó bất cứ nơi nào gần đủ thông tin để xác định chính xác loại trả lại mapInts.

Xin lưu ý rằng điều này đặc trưng cho Scala và có các ngôn ngữ được nhập tĩnh khác (hầu hết họ Miranda / Haskell / Clean, hầu hết họ ML và một vài ngôn ngữ khác) sử dụng thuật toán suy luận toàn diện và có khả năng hơn nhiều hơn Scala sử dụng. Ngoài ra, hãy lưu ý rằng đây không hoàn toàn là lỗi của Scala; Phân nhóm danh nghĩa và suy luận kiểu toàn mô-đun về cơ bản là mâu thuẫn với nhau và các nhà thiết kế của Scala đã chọn ưu tiên cho cái trước vì khả năng tương thích Java, trong khi các ngôn ngữ chức năng được gõ tĩnh "chủ yếu" được thiết kế chủ yếu với lựa chọn ngược lại trong tâm trí.


4
Trên thực tế, vấn đề không phải là quá nhiều để tìm ra một thuật toán suy luận kiểu toàn diện hơn. Đó là tìm ra một thuật toán suy luận kiểu toàn diện hơn, trong khi vẫn giữ được chất lượng cao của các thông báo lỗi trong trình biên dịch Scala hiện tại.
Jörg W Mittag

1
Sẽ không trở lại chính xác cho case Nilthực sự là một sản phẩm nào List[Int]()? Trong trường hợp đó, một trình biên dịch đủ thông minh có thể tìm ra nó. Mặc dù vậy, tất cả đều chơi Devil's Advocate.
KChaloux
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.