Lý do loại bỏ các loại hàm trong Java 8


12

Tôi đã cố gắng hiểu lý do tại sao Nhóm chuyên gia JDK 8 Lambda (EG) quyết định không đưa một loại hàm mới vào ngôn ngữ lập trình Java.

Đi qua danh sách gửi thư tôi tìm thấy một chủ đề với cuộc thảo luận về việc loại bỏ các loại chức năng .

Nhiều tuyên bố không rõ ràng đối với tôi, có thể do thiếu bối cảnh và trong một số trường hợp do kiến ​​thức hạn chế của tôi về việc triển khai các hệ thống loại.

Tuy nhiên, có một vài câu hỏi mà tôi tin rằng tôi có thể xây dựng một cách an toàn trong trang web này để giúp tôi hiểu rõ hơn về ý nghĩa của chúng.

Tôi biết tôi có thể đặt câu hỏi trong danh sách gửi thư, nhưng chủ đề đã cũ và tất cả các quyết định đã được đưa ra, vì vậy rất có thể tôi sẽ bị bỏ qua, trên hết là thấy những kẻ này đã bị trì hoãn với kế hoạch của họ.

Trong câu trả lời của mình để hỗ trợ loại bỏ các loại chức năng và chứng thực việc sử dụng các loại SAM, Brian Goetz nói:

Không thống nhất. Có một chủ đề dài về mức độ hữu ích của các loại chức năng được thống nhất. Không có sự thống nhất, các loại chức năng bị rối loạn.

Tôi không thể tìm thấy chủ đề mà anh ấy đề cập. Bây giờ, tôi có thể hiểu rằng việc giới thiệu một loại hàm cấu trúc có thể ngụ ý một số biến chứng nhất định trong hệ thống loại chủ yếu là danh nghĩa của Java, điều tôi không thể hiểu là các loại SAM được tham số hóa khác nhau như thế nào về mặt thống nhất.

Cả hai đều không phải chịu cùng một vấn đề thống nhất? Có ai hiểu làm thế nào các loại chức năng khác với các loại SAM tham số hóa về mặt thống nhất?

Trong một bình luận khác, Goetz nói:

Có hai cách tiếp cận cơ bản để gõ: danh nghĩa và cấu trúc. Danh tính của một danh nghĩa được dựa trên tên của nó; nhận dạng của một loại cấu trúc dựa trên những gì nó được cấu thành (chẳng hạn như "tuple của int, int" hoặc "hàm từ int đến float".) Hầu hết các ngôn ngữ chọn chủ yếu là danh nghĩa hoặc chủ yếu là cấu trúc; không có nhiều ngôn ngữ kết hợp thành công kiểu gõ danh nghĩa và cấu trúc ngoại trừ "xung quanh các cạnh". Java gần như hoàn toàn trên danh nghĩa (với một vài ngoại lệ: mảng là một kiểu cấu trúc, nhưng ở phía dưới luôn có một kiểu phần tử danh nghĩa; các tổng quát cũng có sự pha trộn giữa danh nghĩa và cấu trúc, và thực tế đây là một phần của nguồn gốc của nhiều về những phàn nàn của mọi người về thuốc generic.) Ghép một hệ thống kiểu cấu trúc (kiểu hàm) lên Java ' s hệ thống danh nghĩa có nghĩa là phức tạp mới và trường hợp cạnh. Là lợi ích của các loại chức năng có giá trị này?

Những bạn có kinh nghiệm trong việc thực hiện các hệ thống loại. Bạn có biết bất kỳ ví dụ về những sự phức tạp hoặc trường hợp cạnh mà anh ấy đề cập ở đây không?

Thành thật tôi bị lẫn lộn bởi những cáo buộc này khi tôi nghĩ rằng một ngôn ngữ lập trình như Scala, hoàn toàn dựa trên JVM, có hỗ trợ cho các kiểu cấu trúc như các hàm và bộ dữ liệu, ngay cả với các vấn đề thống nhất của nền tảng cơ bản.

Đừng hiểu sai ý tôi, tôi không nói rằng một loại chức năng nên tốt hơn các loại SAM. Tôi chỉ muốn hiểu tại sao họ đưa ra quyết định này.


4
"Ghép một hệ thống loại cấu trúc (các loại chức năng) vào hệ thống loại danh nghĩa của Java có nghĩa là sự phức tạp mới" - điều này rất có thể có nghĩa là sự phức tạp đối với người dùng phải học nhiều hơn để sử dụng ngôn ngữ . Một cái gì đó đơn giản và dễ sử dụng Java trở nên giống như C ++ phức tạp và khó học , những thứ như vậy. Các thành viên trong danh sách gửi thư có thể ám chỉ những "làn sóng cải tiến lớn" trước đó, một ví dụ nổi bật là bài viết hút Java 5 của Clinton Begin của MyBatis
gnat

3
"Java đơn giản và dễ sử dụng trở nên phức tạp và khó học C ++": Thật không may, một vấn đề với các ngôn ngữ lập trình chính là chúng phải duy trì khả năng tương thích ngược và do đó chúng có xu hướng trở nên quá phức tạp. Vì vậy, IMHO (có nhiều năm kinh nghiệm với cả C ++ và Java) có một điều gì đó đúng với tuyên bố này. Tôi thường có cảm giác rằng Java nên bị đóng băng và thay vào đó một ngôn ngữ mới sẽ được phát triển. Nhưng Oracle không thể mạo hiểm như vậy.
Giorgio

4
@edalorzo: Như Clojure, Groovy, Scala và các ngôn ngữ khác đã trình bày, có thể (1) định nghĩa một ngôn ngữ mới (2) sử dụng tất cả sự giàu có của các thư viện và công cụ đã được viết bằng Java mà không phá vỡ tính tương thích ngược (3) Các lập trình viên Java có quyền tự do lựa chọn xem họ muốn ở lại với Java, chuyển sang ngôn ngữ khác hay sử dụng cả hai. IMO, mở rộng ngôn ngữ hiện tại vô thời hạn là một chiến lược để giữ khách hàng, giống như cách các công ty điện thoại di động cần tạo ra các mô hình mới mọi lúc.
Giorgio

2
Theo tôi hiểu từ SAMbdas trong Java , một trong những lý do là việc giữ một số thư viện (bộ sưu tập) tương thích trở nên có vấn đề.
Petr Pudlák

2
Bài đăng liên quan trên SO liên kết đến bài đăng khác này của Goetz .
assylias

Câu trả lời:


6

Cách tiếp cận SAM thực sự hơi giống với cách Scala (và C ++ 11) thực hiện với các hàm ẩn danh (được tạo bằng =>toán tử của Scala hoặc C ++ 11[]() cú pháp (lambda)).

Câu hỏi đầu tiên để trả lời ở phía Java là liệu có kiểu trả về của một tuyên bố lambda là một loại primitve mới, như inthay byte, hoặc một loại đối tượng của một số loại. Trong Scala, có không có loại nguyên thủy - thậm chí một số nguyên là một đối tượng của lớp Int- và chức năng cũng không khác, là đối tượng của lớp Function1,Function2 và vân vân, tùy thuộc vào số lượng các đối số chức năng mất.

C ++ 11, ruby ​​và python tương tự có các biểu thức lambda trả về một đối tượng có thể gọi được theo cách rõ ràng hoặc ẩn. Đối tượng được trả về có một số phương thức tiêu chuẩn (chẳng hạn như #callcó thể được sử dụng để gọi nó là một hàm. C ++ 11, ví dụ, sử dụng một std::functionkiểu quá tải operator()để các cuộc gọi của phương thức gọi của đối tượng thậm chí trông giống như các cuộc gọi hàm, theo văn bản. :-)

Trường hợp đề xuất mới cho Java trở nên lộn xộn là việc sử dụng kiểu gõ cấu trúc để cho phép gán một phương thức như vậy cho một đối tượng khác, chẳng hạn như một Comparatorphương thức có một phương thức chính duy nhất có tên khác . Mặc dù điều này về mặt khái niệm là khó hiểu, nhưng điều đó có nghĩa là đối tượng kết quả có thể được chuyển đến các hàm hiện có để lấy một đối tượng để biểu diễn một cuộc gọi lại, một bộ so sánh, v.v. và mong đợi có thể gọi một đơn được xác định rõ phương pháp như #comparehoặc#callback . Thủ thuật ghi đè operator()gọn gàng của C ++ đã tránh được vấn đề này ngay cả trước C ++ 11, vì tất cả các tùy chọn gọi lại như vậy đều có thể gọi theo cùng một cách, và do đó STL không yêu cầu điều chỉnh để cho phép sử dụng lambd C ++ 11sortvà như thế. Java, trước đây không sử dụng cách đặt tên tiêu chuẩn cho các đối tượng như vậy (có lẽ vì không có mánh khóe nào như quá tải toán tử làm cho một cách tiếp cận rõ ràng), nên không may mắn, vì vậy, việc hack này ngăn chúng khỏi phải thay đổi toàn bộ API hiện có .


1
Trớ trêu thay, vấn đề nếu có vô số loại khác nhau, không tương thích, tất cả đại diện cho một loại "thứ giống như chức năng" có thể tránh được một cách gọn gàng bằng cách thêm sớm các loại hàm tiêu chuẩn vào thư viện, độc lập với việc có cú pháp nghĩa đen thực sự để xây dựng chúng. Nếu đã có java.util.Function2<T1, T2, R>Java 1.0, thì sẽ không có Comparatorgiao diện, thay vào đó tất cả các phương thức đó sẽ mất một Function2<T1, T2, int>. (Vâng, sẽ có được một vùng toàn bộ giao diện như Function2TT_int<T1, T2>vì nguyên thủy, nhưng bạn sẽ có được quan điểm của tôi.)
Jörg W Mittag
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.