2010-02-05 47 views
27

Tại sao Scala không suy ra kiểu trả về của phương thức khi có câu lệnh return rõ ràng được sử dụng trong phương thức?Loại suy luận về phương thức trả về loại

Ví dụ: tại sao mã sau biên dịch?

object Main { 
    def who = 5 
    def main(args: Array[String]) = println(who) 
} 

Nhưng những điều sau thì không.

object Main { 
    def who = return 5 
    def main(args: Array[String]) = println(who) 
} 

Trả lời

30

Kiểu trả về của một phương thức là kiểu của câu lệnh cuối cùng trong khối xác định nó hoặc loại biểu thức xác định nó, trong trường hợp không có khối.

Khi bạn sử dụng return bên trong một phương pháp, bạn giới thiệu một tuyên bố khác mà từ đó phương thức có thể trả lại. Điều đó có nghĩa là Scala không thể xác định loại đó return tại thời điểm nó được tìm thấy. Thay vào đó, nó phải tiến hành cho đến khi kết thúc phương thức, sau đó kết hợp tất cả các điểm thoát để suy ra các loại của chúng, và sau đó quay lại từng điểm thoát và gán các kiểu của chúng.

Để làm như vậy sẽ làm tăng độ phức tạp của trình biên dịch và làm chậm nó xuống, vì lợi ích duy nhất của việc không phải chỉ định kiểu trả về khi sử dụng return. Trong hệ thống hiện tại, mặt khác, suy ra kiểu trả về đến miễn phí từ suy luận kiểu giới hạn Scala đã sử dụng.

Vì vậy, cuối cùng, trong sự cân bằng giữa độ phức tạp của trình biên dịch và số lợi ích cần có, cái sau được coi là không đáng giá.

+5

Xin chào Daniel. Tôi không nhận được lời giải thích của bạn. Scala đã phải kết hợp nhiều biểu thức và các điểm thoát trong các hàm do các câu lệnh if/else. Và ngôn ngữ Scala có rất nhiều thứ phức tạp trong đó IMO mà hầu hết các lập trình viên Scala không hiểu rõ hoặc sử dụng (ví dụ: hiệp phương sai/contravariance, các kiểu cấu trúc, vv). Điều này cho biết thêm rất nhiều phức tạp cho trình biên dịch; vì vậy "làm cho trình biên dịch phức tạp hơn" có vẻ như một câu trả lời yếu. –

+4

@UrbanVagabond Bạn đã bỏ lỡ phần "lợi ích để trở thành người đứng đầu". Chỉ vì một cái gì đó phức tạp không có nghĩa là nó đáng giá thêm độ phức tạp hơn cho nó. Bây giờ, Scala không phải kết hợp nhiều biểu thức và các điểm thoát trên các câu lệnh if/else vì nếu/else là một biểu thức, không phải là các câu lệnh. Điều đó có vẻ như tách tóc, nhưng sự khác biệt là rất thực tế. –

-2

Tôi không chắc chắn lý do. Có lẽ chỉ để ngăn cản việc sử dụng câu lệnh return. :)

1

Với này (2.8.Beta1):

object Main { 
    def who = return 5 
    def main(args: Array[String]) = println(who) 
} 
<console>:5: error: method who has return statement; needs result type 
     def who = return 5 

... có vẻ như không ngoài ý muốn.

11

Nó sẽ làm tăng độ phức tạp của trình biên dịch (và ngôn ngữ). Nó chỉ thực sự sôi nổi để làm suy luận kiểu trên một cái gì đó như thế. Như với bất kỳ kiểu suy luận nào liên quan, tất cả đều hoạt động tốt hơn khi bạn có một biểu thức duy nhất. Các báo cáo trả về phân tán có hiệu quả tạo ra rất nhiều phân nhánh tiềm ẩn được gắn kết để thống nhất. Nó không phải là nó đặc biệt cứng, chỉ dính. Ví dụ:

def foo(xs: List[Int]) = xs map { i => return i; i } 

Điều gì, tôi hỏi bạn, trình biên dịch có suy luận ở đây không? Nếu trình biên dịch đã làm suy luận với các câu lệnh trả về rõ ràng, nó sẽ cần phải là Any. Trên thực tế, rất nhiều phương thức có báo cáo trả về rõ ràng sẽ kết thúc trả về Any, ngay cả khi bạn không bị lén lút với trả về không phải cục bộ. Như tôi đã nói, dính.

Và trên hết, đây không phải là tính năng ngôn ngữ nên được khuyến khích. Lợi nhuận rõ ràng làm không cải thiện độ rõ của mã trừ khi chỉ có một lần trả về rõ ràng và ở cuối hàm. Lý do là khá dễ dàng để xem nếu bạn xem đường dẫn mã như một đồ thị đạo diễn. Như tôi đã nói trước đó, lợi nhuận phân tán tạo ra rất nhiều phân nhánh tiềm ẩn tạo ra những chiếc lá kỳ lạ trên đồ thị của bạn, cũng như nhiều đường dẫn bổ sung trong cơ thể chính. Nó chỉ là sôi nổi. Luồng điều khiển dễ dàng hơn nhiều để xem liệu các nhánh của bạn có rõ ràng hay không (mẫu phù hợp hoặc biểu thức if) và mã của bạn sẽ hoạt động nhiều hơn nếu bạn không dựa vào các câu lệnh có hiệu lực bên cạnh để tạo ra các giá trị.

Vì vậy, giống như nhiều tính năng khác "nản" trong Scala (ví dụ asInstanceOf hơn as), các nhà thiết kế của ngôn ngữ tạo ra một sự lựa chọn có chủ ý để làm cho mọi việc ít dễ chịu. Điều này kết hợp với sự phức tạp mà nó đưa vào suy luận kiểu và tính vô dụng thực tế của các kết quả trong tất cả trừ các kịch bản nhiều nhất. Nó không có ý nghĩa gì đối với scalac để thử kiểu suy luận này.

Đạo đức của câu chuyện: học cách không phân tán lợi nhuận của bạn! Đó là lời khuyên tốt trong bất kỳ ngôn ngữ nào, không chỉ là Scala.

+0

@ Daniel ... "chán nản" các tính năng trong Scala (ví dụ như asInstanceOf chứ không phải là) ".... Tôi đã bỏ lỡ một cái gì đó? Tôi không nhớ 'như' như là một chức năng trong Scala (nhưng tôi khá mới để Scala Vì vậy, nó có thể là sai lầm của tôi) – Jus12

+0

@ Daniel, tôi nghĩ rằng một đề nghị tốt hơn nữa là tránh sử dụng 'return's (liên quan: http://stackoverflow.com/questions/3770989/purpose-of-return-statement -in-scala) – Jus12

+1

Không có hàm 'as' trong Scala. Có một toán tử' as' trong C# mặc dù các hàm đó giống như phương thức 'asInstanceOf' trong Scala. Rất nhiều người mới sử dụng câu hỏi ngôn ngữ tại sao cơ chế cast của Scala –

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