Lập trình hàm có khả thi trong Java không? [đóng cửa]


42

Tôi đang duyệt qua Cửa hàng sách Amazon.com và tôi đã tìm thấy cuốn sách "Lập trình chức năng cho các nhà phát triển Java" .

Tôi biết một số Lập trình hàm rất cơ bản và đã lập trình bằng Java được 3 năm.

Tôi muốn biết Lập trình hàm có khả thi trong Java không?


2
Phong cách là có thể nhưng tính dài dòng của nó có thể quá sức chịu đựng cú pháp của Java: functionjava.org
Yuriy Zubarev

7
@nCdy Tại sao phải kiểm tra JRuby? vui lòng cung cấp thêm lời giải thích.
Chiron

1
kiểm tra Groovy :-)
Ant's

6
Tôi nghĩ rằng đây là loại câu hỏi làm tăng sự khác biệt giữa ngôn ngữ Java và nền tảng Java.
Thomas Owens

2
@ ThorbjørnRavnAndersen: Điều gì khiến bạn nghĩ rằng "lập trình chức năng" được định nghĩa bằng "đánh giá lười biếng"? Có vẻ là một ví dụ kỳ lạ để chọn ...
John Bartholomew

Câu trả lời:


70

Nó phụ thuộc vào những gì bạn có nghĩa là "lập trình chức năng" và "có thể".

Bạn rõ ràng có thể thực hiện những điều theo một mô hình chức năng. Tuy nhiên, ngôn ngữ Java không cung cấp đường cú pháp cho nó, vì vậy một số thứ sẽ tẻ nhạt nhất và một số ngôn ngữ khác sẽ cực kỳ phức tạp.

Tương tự, bạn rất có thể viết mã hướng đối tượng bằng một ngôn ngữ được công nhận là không phải OO, như C.

Thư viện Java

Có những thư viện có thể giúp bạn làm điều này, bằng cách thực hiện các công việc cần thiết cho bạn và che giấu những điều phức tạp:

Những thứ này sẽ cho phép bạn viết mã Java với cách tiếp cận chức năng hơn và có thể là cú pháp và ngữ nghĩa quen thuộc hơn, như bạn mong đợi từ một ngôn ngữ có thẩm quyền của FP. Trong lý do, đó là.

Ngôn ngữ JVM

Và rõ ràng, bạn có thể triển khai một ngôn ngữ chức năng trên Java. Vì vậy, sau đó bạn có thể sử dụng ngôn ngữ đó làm ngôn ngữ FP của bạn. Đó là một chút của mức độ trừu tượng cao hơn so với những gì bạn yêu cầu, nhưng tương đối trong bối cảnh (mặc dù tôi gian lận một chút ở đây, được cấp).

Ví dụ: kiểm tra:

Các ngôn ngữ JVM ít nhiều chức năng

Mặc dù chúng có thể không chính xác như bạn muốn, nhưng có một số ngôn ngữ khác đã được chuyển sang Nền tảng Java và điều đó có thể giải phóng bạn khỏi bản chất tương đối không có định hướng (có ý định chơi chữ) của Java và đã cung cấp cho bạn nhiều hơn Uyển chuyển. Các ứng cử viên đáng chú ý như JRuby , JythonRhino (tương ứng cho Ruby , PythonJavaScript / ECMAScript ) cũng mang đến tiềm năng thú vị cho lập trình chức năng, mặc dù về bản chất chúng không phải là ngôn ngữ lập trình chức năng. JetBrains' Kotlin, trong khi thừa nhận rõ ràng nó không phải là ngôn ngữ chức năng, nó hỗ trợ một số cấu trúc chức năng và cũng đáng xem.

Đọc thêm

Bạn cũng có thể muốn đọc hoặc xem các bài viết hoặc video này:


2
Mã nguồn Clojure hiện được lưu trữ trên Github github.com/clojure/clojure
Chiron

@ The Legend of 1982: Tôi đã nhanh hơn bình luận của bạn, tôi đã thay đổi liên kết đến trang web clojure.org chính thức :) Nhưng cảm ơn vì đã nắm bắt nó rất nhanh! Thật tốt khi thấy mọi người phản ứng nhanh.
haylem

Ngoài ra còn có ABCL ( common-lisp.net/project/armedbear ), nhưng tôi không biết nó rơi vào thang trưởng thành / không trưởng thành và đó là một triển khai Lisp chung.
Vatine

@Vatine: thú vị, hoàn toàn chưa bao giờ nghe nói về nó. Sẽ có một cái nhìn nhanh chóng và thêm nó.
haylem

1
Tôi yêu thuật ngữ "Turing Tarpit" của Alan Perlis vì đã cố gắng làm điều gì đó mà một kẻ yếu đuối có thể làm (vì nó đã hoàn thành) nhưng chỉ với nỗi đau và sự phức tạp đến mức không nên thử.
itbruce

11

Tôi đang đọc cuốn sách mà bạn đề cập. Nó thực sự là BTW tốt.

Vâng, nó có thể hoạt động được trong Java. Tôi không biết bạn có thể đạt được mức độ nào nhưng bạn có thể thực hiện nhiều thành ngữ lập trình chức năng.

Một trong những điều quan trọng nhất là cố gắng viết mã với tâm lý "Đừng biến đổi trạng thái".

Ví dụ, bạn sử dụng từ khóa cuối cùng để đạt được sự bất biến. Nếu bạn định sử dụng cấu trúc dữ liệu thì bạn nên mã trong cấu trúc dữ liệu bất biến. Thư viện Google Guava đã làm điều này.

Ngoài ra để lập trình đồng thời, bạn có thể dựa vào khung Akka (mô hình diễn viên).

Điều đáng nói là mã byte JVM không hỗ trợ (ít nhất là) Tối ưu hóa cuộc gọi đuôi, một tính năng rất quan trọng đối với các ngôn ngữ lập trình chức năng.


"Điều đáng nói là mã byte JVM không hỗ trợ (ít nhất là) Tối ưu hóa cuộc gọi đuôi, một tính năng rất quan trọng đối với các ngôn ngữ lập trình chức năng.": Ý bạn là gì? Scala không có TCO.
Giorgio

@Giorgio: Scala hiện TCO tại thời điểm biên dịch.
Scrwtp

@scrwtp: Có bị phạt hiệu suất vì điều đó không? Hoặc những nhược điểm của TCO thời gian biên dịch là gì?
Giorgio

@Giorgio: Ý tôi là java bytecode không hỗ trợ nó, giống như Chiron đã nêu ban đầu. Các ngôn ngữ chức năng hoạt động xung quanh nó, biên dịch các cuộc gọi đệ quy thành các vòng lặp, nhưng đó là một tính năng của ngôn ngữ-> trình biên dịch mã byte, không phải là JVM.
xem xét

@scrwtp: Câu trả lời của Chiron nói rằng "Điều đáng nói là mã byte JVM không hỗ trợ (ít nhất là) Tối ưu hóa cuộc gọi đuôi, một tính năng rất quan trọng đối với các ngôn ngữ lập trình chức năng." làm cho nó có vẻ như việc triển khai một ngôn ngữ chức năng trên JVM bị phạt nhưng (và chúng tôi dường như đồng ý về điều này) điều này không đúng vì tối ưu hóa cuộc gọi đuôi có thể được mô phỏng trong mã được biên dịch. Vì vậy, tôi đồng ý với tuyên bố của Chiron nhưng tôi thấy nó hơi sai lệch.
Giorgio

6

Vâng, điều đó là hoàn toàn có thể , theo cùng một cách mà nó có thể xảy ra trong bất kỳ tổ hợp ngôn ngữ / môi trường thực thi hoàn chỉnh nào. Bạn thậm chí có thể làm cho nó hoạt động khá tốt nếu bạn biết những gì bạn đang làm.

Không chắc nó hợp lý như thế nào. Đặc biệt, lưu ý rằng nó không đặc biệt thành ngữ (nghĩa là nó sẽ trông rất lạ, bạn sẽ phải làm một số điều khác thường và gây nhầm lẫn cho những người đã quen với Java thông thường)

Bạn sẽ kết thúc với một số mã tìm kiếm kỳ lạ, ví dụ để xác định một chức năng mới:

Function twoStrings=new Function() {
  public Object apply(Object param1) {
    // do something to param1 and return a result
  }
}

Để làm lập trình chức năng bạn thường cần:

  • Các hàm hạng nhất - dễ dàng tạo trong Java bằng cách định nghĩa một lớp hoặc giao diện trừu tượng đại diện cho "Hàm" của bạn và có phương thức "áp dụng" áp dụng hàm cho một hoặc nhiều tham số.
  • Đóng - tạo một thể hiện của đối tượng chức năng của bạn ở trên với các giá trị đóng được lưu trữ trong các trường cuối cùng. Bạn có thể sử dụng một lớp bên trong ẩn danh cho việc này.
  • Một thư viện các hàm bậc cao tiêu chuẩn - điều này khó hơn, tuy nhiên bạn vẫn có thể tự viết để khởi động một ngôn ngữ chức năng đơn giản trong vài giờ. Nếu bạn muốn một cái gì đó lạ hơn, bạn có thể kiểm tra các thư viện chức năng khác mà mọi người đã xây dựng bằng Java.

Vì vậy, nó có thể là một bài tập và thậm chí là một dự án sở thích thú vị. Nhưng bạn thực sự muốn lập trình chức năng nghiêm túc trong khi vẫn duy trì các lợi thế của JVM / truy cập các thư viện Java thì theo tôi, Clojure là lựa chọn tốt nhất của bạn.

Vì lõi của Clojure thực sự được viết bằng Java, đây thực sự là một ví dụ rất thú vị về cách thực hiện lập trình chức năng trong Java trong khi ẩn các chi tiết lộn xộn đằng sau một cú pháp ngôn ngữ hiện đại mới. Mã nguồn Clojure có trên GitHub cho những ai quan tâm.


Thật thú vị, tôi đã nhận thấy rằng phiên bản mới nhất của IntelliJ IDEA sẽ gấp những cái ẩn danh này thành một hình thức nhỏ gọn hơn để hiển thị trong trình chỉnh sửa. Liệu một công việc tốt đẹp của việc che giấu các hành trình dư thừa. Tất nhiên tất cả những điều này sẽ không liên quan đến Java 8.
Ben Hardy

4

Có thể là một số chức năng trong Java. Làm như vậy là đau đớn nghiêm trọng . Thay vì

myList.each { doSomething(it); }

Bạn có một cái gì đó như:

myList.each(new Function() { public void do(Object arg) { something(); }})

Và nếu bạn muốn lập trình chức năng thực sự, với các bao đóng và các hàm như các đối tượng hạng nhất, hãy chọn một ngôn ngữ khác. Scala, Clojure, Groovy đều chạy trên JVM và có thể tương tác với các lớp Java kế thừa. .


Lập trình hàm không sử dụng các khối thay vì các lớp ẩn danh. Java 8 sẽ có các khối, vì vậy mã được đăng của bạn sẽ trông thanh lịch hơn nhưng nó sẽ không phải là lập trình chức năng.
Chiron

@Legend: Tôi hiểu điều đó, nhưng rõ ràng là không giải thích rõ về nó.
kevin cline

Đây là giám sát / dưới mức. với bất kỳ ngôn ngữ nào, bạn phải thực sự xác định hàm SOMEWHERE, bạn không thể bỏ qua phần đó. Vì vậy, Java gần như ngắn gọn, tất cả những gì bạn phải làm là làm cho đối tượng Hàm không đồng nghĩa. Bạn có thể làm điều này: Hàm f = new Function () {public void do () {}}; .... sau đó ... gọi hàm đó .... myMethodToCallAFunction (Hàm f) {f.do ()} ... đó là nó, bros và brolinis. đối phó với nó.
Alexander Mills

3

Câu trả lời là "có, tất nhiên" vang dội, nhưng theo tôi, một trong những tính năng quan trọng nhất trong nhiều ngôn ngữ chức năng là hệ thống loại tuyệt vời. Bạn sẽ không bao giờ có thể tự quản lý điều này trong Java.

Nếu bạn muốn viết các chương trình chức năng và vẫn ở lại với JVM, tôi có thể đề nghị trong số các nghi phạm thông thường Scala và Clojure xem xét Frege . Frege có một hệ thống cú pháp và kiểu rất gần với Haskell, nhưng các chương trình được dịch trực tiếp sang mã java và có thể tương tác với mã java khác.


2

Vâng, tất cả các loại điều có thể. Có thể thực hiện lập trình hướng đối tượng trong C; nó không phải là một ý tưởng tốt

Java không được thiết kế cho FP, vì vậy nếu bạn đang cố gắng làm mọi thứ theo kiểu hoàn toàn FP, bạn sẽ gặp vấn đề. Bạn sẽ chiến đấu với ngôn ngữ, thay vì làm việc với nó. Và không chỉ ngôn ngữ - còn có tất cả các thư viện Java miễn phí tuyệt vời. Vì vậy, đừng đi cho FP thuần túy; lấy một số ý tưởng đằng sau FP và tích hợp chúng vào mã Java của bạn, nhưng hiểu rằng bạn không thể làm điều đó với tất cả các ý tưởng.


0

Bạn được nhóm OpenJDK khuyến khích tải xuống các tệp nhị phân OpenJDK 8 mới nhất của họ và chơi xung quanh với các biểu thức lambda mới và các thành ngữ chức năng mới được giới thiệu trong Bộ sưu tập API (trong số những thứ khác). Bạn có thể lập trình theo một phong cách chức năng rõ ràng. Xem "Lập trình hàm trong Java?" để so sánh Bộ sưu tập JDK8 với các lib trước Java8 như Guava, FunctionalJava và LambdaJ.


-3

Có vẻ như có thể nhưng nó sẽ không phải là một chương trình chức năng thuần túy. Nó có thể dẫn đến lập trình mệnh lệnh.

Không có câu hỏi tại sao ông có nghĩa là có thể lập trình chức năng như được đề cập bởi haylem. Đây là:

Nó phụ thuộc vào những gì bạn có nghĩa là "lập trình chức năng" và "có thể".

Lập trình hàm có thể có các định nghĩa hoặc ý nghĩa khác nhau mặc dù nó có thể có nhiều giải thích.
Giống như OOP, chúng ta có thể hỏi "ý của OOP là gì?".
Chắc chắn sẽ có rất nhiều lời giải thích nhưng nó sẽ chỉ liên quan đến một mục tiêu, mục tiêu của OOP.
Điều tương tự cũng áp dụng cho lập trình chức năng .

Khi chúng ta nói chức năng có nghĩa là các chương trình bao gồm các chức năng.
Vai trò của các hàm là trả về một đối số / tham số được đánh giá (đối số là biến là biểu thức xuất hiện khi gọi hàm trong khi tham số là biến là một phần của khai báo hàm).

Ngoài ra các hàm sẽ luôn trả về cùng một kết quả khi các đối số tương tự được thông qua. Theo cách đó, dễ dàng hơn để tránh các lỗi hoặc gỡ lỗi các lỗi trong tương lai. Bằng lập trình chức năng, chúng ta có thể tránh các tác dụng phụ như sửa đổi biến toàn cục.

ví dụ trong JavaScript:

function increment(lis){
    return lis.map(
        function (x){
            return x+2;
        }
    );
}

var myList = [4, 7, 2, 3];
console.log(increment(myList));
console.log(myList);

Gia số hàm thêm 1 giá trị cho mỗi phần tử bên trong đối tượng và trả về kết quả. Giá trị của myList không thay đổi nhưng khi chúng ta gọi các hàm, chúng ta đã thấy giá trị gia tăng cho các phần tử của đối tượng đó.

Theo phản hồi của tôi về Lập trình chức năng có thể có trong Java không? , Tôi tin rằng không thể có lập trình chức năng thực sự trong java. Bởi vì java thực sự được thiết kế để trở thành OOP, trong đó nó mở rộng lập trình bắt buộc và cải thiện nó để duy trì. Khi trạng thái của một đối tượng, biến vv, đã thay đổi, đó đã là một chương trình bắt buộc.

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.