2014-10-11 20 views
5

Trong Java 8 gói mới java.util.function chứa rất nhiều giao diện chức năng. Các tài liệu cho gói phần mềm đó (http://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html) làm cho một số tài liệu tham khảo để "chức năng hình dạng":"Hình dạng chức năng" liên quan đến các giao diện chức năng trong Java 8 là gì?

  • Có một số cơ bản chức năng hình dạng, bao gồm cả chức năng (chức năng unary từ T R), người tiêu dùng (chức năng unary từ T đến void), Predicate (hàm unary từ T đến boolean) và Supplier (hàm nilary thành R).
  • Hình dạng chức năng có tính chất tự nhiên dựa trên cách chúng được sử dụng phổ biến nhất. Các hình dạng cơ bản có thể được sửa đổi bởi tiền tố arity để biểu thị một vị trí khác, chẳng hạn như BiFunction (hàm nhị phân từ T và U đến R).
  • Có thêm các hình dạng chức năng có nguồn gốc bổ sung để mở rộng các hình dạng chức năng cơ bản , bao gồm UnaryOperator (mở rộng chức năng) và BinaryOperator (mở rộng chức năng).

Tôi chưa bao giờ nghe thuật ngữ "hình dạng chức năng" trước đây, và tôi hầu như không tìm thấy tham chiếu đến nó ở bất kỳ đâu ngoại trừ trong tài liệu ở trên, nhưng đó là tài liệu chính thức của Oracle về giao diện chức năng mà tôi muốn hiểu nó.

Bất kỳ ai cũng có thể cung cấp định nghĩa về "hình dạng chức năng" và tạo một ví dụ? Nó là một thuật ngữ chung trong Khoa học Máy tính, hay nó chỉ liên quan đến Java 8? Và làm thế nào là hình dạng chức năng liên quan đến một bộ mô tả chức năng (chẳng hạn như (T) -> boolean cho Giao diện người dùng <T>)?

CẬP NHẬT Hai nhận xét bên dưới từ Brian Goetz trả lời các câu hỏi tôi nêu trong bài đăng này.

+0

duy nhất (không chính thức) tài liệu tham khảo để định hình trong JLS là ở dưới cùng của [15.12.2.1] (http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2.1). – assylias

+0

"hình dạng" cũng được đề cập trong [JSR 335] (https://jcp.org/aboutJava/communityprocess/final/jsr335/index.html), Phần F; nhưng nó luôn được đặt trong dấu ngoặc kép và không có định nghĩa rõ ràng cho nó. – stakx

+0

Các tham chiếu trong JLS và JSR335 thành "hình dạng" là các câu giống hệt nhau và tham chiếu có lẽ được sao chép từ một tài liệu sang tài liệu khác. Từ ngữ cảnh, có vẻ như "hình dạng chức năng" bằng cách nào đó liên quan đến việc đánh giá thời gian chạy (trong khi một "bộ mô tả hàm" rõ ràng được biết là biên dịch). – skomisa

Trả lời

2

Một hình dạng chức năng cơ bản là những gì đầu vào và đầu ra của nó như thế nào, về các thông số type:

  • Một chức năng unary mất một đầu vào và trả về một đầu ra [T → R]
  • Một nhị phân chức năng có hai đầu vào và trả về một đầu ra [(T, U) → R]
  • một chức năng ternary mất ba đầu vào và trả về một đầu ra [(T, U, V) → R]
  • một nhà cung cấp (còn gọi là một hàm null) không có đầu vào và trả về một đầu ra [() → R]
  • Một người tiêu dùng mất một đầu vào và không trả lại bất kỳ đầu ra [T →()]
  • Một vị unary mất một đầu vào và trả về một đầu ra của boolean loại [ T → bool]
  • một vị nhị phân có hai đầu vào và trả về một đầu ra của boolean loại [(T, U) → bool]
  • một nhà điều hành unary mất một đầu vào và trả về một đầu ra cùng loại [T → T ]
  • Toán tử nhị phân lấy hai đầu vào cùng loại và trả về một đầu ra giống nhau nhập [(T, T) → T]

Có nhiều hình dạng khác, nhưng đó là những hình dạng phổ biến.

+1

Nhưng nếu đúng như vậy thì Function và Predicate sẽ có cùng một hình dạng: cả hai đều lấy một đầu vào và trả về một đầu ra [1 → 1]. Tuy nhiên, tài liệu được trích dẫn ở trên mô tả rõ ràng các giao diện đó có các hình dạng khác nhau. Bạn có thể đang ở trên các dòng bên phải, nhưng tôi không chắc chắn rằng các loại có thể được bỏ qua. – skomisa

+2

@skomi Đúng vậy, có lẽ tốt hơn là nên cuộn các loại vào cuộc thảo luận. Đặc biệt, kể từ đó, có các hàm unary chung ('T -> U'), các biến vị ngữ (' T -> bool'), và toán tử ('T -> T'), mỗi cái có một cảm giác khác nhau. Hãy sửa đổi bài đăng của tôi. –

+0

@stakx Định nghĩa của bạn có vẻ gần với "hàm mô tả", như được định nghĩa trong JSR335: "Bộ mô tả hàm của giao diện chức năng I là một kiểu phương thức — các tham số kiểu, kiểu tham số chính thức, kiểu trả về và kiểu ném - có thể được sử dụng để ghi đè một cách hợp pháp (các) phương thức trừu tượng của tôi ". Đó là tốt, nhưng mời các câu hỏi: sự khác biệt giữa một "hình dạng chức năng" và một "chức năng desccriptor" là gì? – skomisa

2

Tôi không tìm thấy bất kỳ tham chiếu nào đến định nghĩa chính thức hoặc được chấp nhận rộng rãi về cụm từ "hình dạng chức năng", vì vậy những điều sau đây là cách giải thích của riêng tôi.

A "chức năng hình" dường như là "type signature" including the return type của nó, tức là mô tả tổng của:

  • một danh sách đặt/tuple của các loại thông số của nó, và
  • kiểu trả về của nó

(Đó là, về cơ bản tất cả mọi thứ về một hàm ngoại trừ tên hàm, tên tham số và phần thân.) Tôi nghi ngờ rằng họ không sử dụng thuật ngữ "chữ ký" vì nó đã có ý nghĩa khác trong Java — nó không bao gồm sự trở lại kiểu. Vì vậy, họ đã phát minh ra một thuật ngữ mới.

Trong ngôn ngữ lập trình chức năng, "nhập chữ ký" thường bao gồm loại trả về. Chữ ký rất hữu ích trong việc hiểu những gì một chức năng có thể làm, vì vậy chúng thường được viết xuống một cách rõ ràng. Ví dụ, chữ ký (hoặc "hình dạng chức năng" trong thuật ngữ Java) cho BiFunction mới có thể được viết thành (T, U) -> R, trong đó phần đầu tiên là một bộ đại diện cho danh sách tham số và phần thứ hai là kiểu trả về.

Do đó, tôi không đồng ý với this other answer: Tôi nghĩ rằng các loại vấn đề và là không phải là bị bỏ qua. Nếu chúng bị bỏ qua, thì một số loại được xác định trong không gian tên mới sẽ có cùng một hình dạng chức năng giống nhau (ví dụ: Supplier, Predicate, Function). Nếu đó là như vậy, thì tại sao tài liệu sẽ chọn giải thích các loại mới này với khái niệm không phù hợp về các hình dạng chức năng? Điều đó không có ý nghĩa. (Câu trả lời đã được chỉnh sửa.)

Dưới đây là một vài chi tiết ví dụ về chữ ký kiểu chức năng cho các giao diện chức năng Java mới:

BiFunction<T,U,R>,   (T, U) -> R 
BinaryOperator<T,U,R>   (T, U) -> R 
BiPredicate<T,U>    (T, U) -> boolean 
Consumer<T>     T  ->()   note: `()` means `void` 
Function<T,R>     T  -> R 
IntFunction<R>    int -> R 
Predicate<T>     T  -> boolean 
Supplier<R>     ()  -> R 
UnaryOperator<T,R>   T  -> R 
+1

Ý của bạn là "T, U -> R" thay vì "T -> U -> R"? – skomisa

+2

@skomi Vâng, đó là (T, U) -> R, nhưng, đối với những người quen với việc sử dụng các ngôn ngữ currying (như Haskell), nó thực sự sẽ là T-> U-> R. –

+1

@skomi: Tôi đã xóa phần trả lời đó trong thời gian chờ đợi. Không, tôi thực sự có nghĩa là 'T -> U -> R', vì ngôn ngữ progrmaming chức năng thường cho phép currying, và tôi đã nói về lập trình chức năng nói chung. Nhưng kể từ khi currying không liên quan đến Java, gợi ý của bạn '(T, U) -> R' thực sự sẽ thích hợp hơn. Cảm ơn vì sự đúng đắn của bạn! – stakx

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