2014-10-11 11 views
5

In Java 8 il nuovo pacchetto java.util.function contiene molte interfacce funzionali. La documentazione per quel pacchetto (http://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html) contenga molti riferimenti alle "forme funzione":Che cos'è una "forma di funzione" rispetto alle interfacce funzionali in Java 8?

  • Ci sono parecchi di base funzione forme, compresa la funzione (funzione unaria da T a R), dei consumatori (funzione unaria da T a vuoto), Predicato (funzione unaria da T a booleano) e Fornitore (funzione nilare a R).
  • Le forme di funzione hanno un'origine naturale basata sul modo in cui vengono utilizzate più comunemente. Le forme base possono essere modificate da un prefisso arity per indicare un'arità diversa, ad esempio BiFunction (funzione binaria da T e da U a R).
  • ci sono ulteriori derivato funzione figure che si estendono la funzione di base forme, compreso UnaryOperator (estende Funzione) e BinaryOperator (estende BiFunction).

non avevo mai sentito parlare del termine "forma la funzione" prima, e posso a malapena a trovare un riferimento ad esso ovunque tranne nella documentazione di cui sopra, ma dal momento che è documentazione formale di Oracle su interfacce funzionali che vorrei capiscilo.

Qualcuno può fornire una definizione di "forma di funzione" e inventare un esempio? È un termine generico in Informatica o si riferisce solo a Java 8? E in che modo la forma della funzione è correlata a un descrittore di funzione (come (T) -> booleano per l'interfaccia del predicato <T>)?

UPDATE I due commenti seguenti di Brian Goetz rispondono alle domande che ho sollevato in questo post.

+0

L'unica (informale) riferimento alla forma nella JLS è in fondo [15.12.2.1] (http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2.1). – assylias

+0

"forma" è anche menzionato in [JSR 335] (https://jcp.org/aboutJava/communityprocess/final/jsr335/index.html), Parte F; ma è sempre messo tra virgolette e non esiste una definizione esplicita per questo. – stakx

+0

I riferimenti in JLS e JSR335 a "forma" sono in frasi identiche e il riferimento è presumibilmente copiato da un documento all'altro. Dal contesto sembra che la "forma della funzione" sia in qualche modo correlata alla valutazione del tempo di esecuzione (mentre un "descrittore di funzione" è ovviamente noto alla compilazione). – skomisa

risposta

2

Una forma funzione è sostanzialmente quello che gli ingressi e le uscite assomigliano, in termini di parametri di tipo:

  • Una funzione unario accetta un ingresso e restituisce un'uscita [T → R]
  • Un binario funzione prende due ingressi e restituisce un'uscita [(T, U) → R]
  • una funzione ternaria prende tre ingressi e restituisce un'uscita [(T, U, V) → R]
  • un fornitore (noto anche come una funzione nulla) prende nessun ingresso e restituisce un'uscita [() → R]
  • Un consumatore prende un ingresso e non restituisce alcun output [T →()]
  • Un predicato unario accetta un ingresso e restituisce un'uscita di tipo booleano [ T → bool]
  • un predicato binario prende due ingressi e restituisce un'uscita di tipo booleano [(T, U) → bool]
  • operatore unario accetta un ingresso e restituisce un'uscita dello stesso tipo [T → T ]
  • Un operatore binario prende due ingressi dello stesso tipo e restituisce un'uscita dello stesso type [(T, T) T]

Ci sono molte altre forme, ma quelle sono quelle comuni.

+1

Ma se così fosse, allora Funzione e Predicato avrebbero la stessa forma: entrambi accettano un input e restituiscono un output [1 → 1]. Tuttavia, la documentazione sopra citata descrive esplicitamente tali interfacce come aventi forme diverse. Potresti essere sulla linea giusta, ma non sono sicuro che i tipi possano essere ignorati. – skomisa

+2

@skomi È vero, forse è meglio inserire i tipi nella discussione. Tanto più che ci sono funzioni unarie generali ('T -> U'), predicati (' T -> bool'), e operatori ('T -> T'), ognuno dei quali ha una sensazione diversa dall'altro. Fammi modificare il mio post. –

+0

@stakx La tua definizione sembra vicina a quella di "descrittore di funzione", come definito in JSR335: "Il descrittore di funzione di un'interfaccia funzionale I è un parametro di tipo tipo di metodo, tipi di parametri formali, tipi di ritorno e tipi lanciati, che possono essere usato per ignorare legalmente il metodo (i) astratto di I ". Va bene, ma invita la domanda: qual è la differenza tra una "forma di funzione" e una "funzione desccriptor"? – skomisa

2

Non ho trovato alcun riferimento a una definizione ufficiale o ampiamente accettata del termine "forma di funzione", quindi quello che segue è la mia interpretazione personale.

A "di figura funzione" appare essere il suo "type signature" including the return type, cioè la descrizione somma:

  • un elenco/tupla ordinata dei tipi dei suoi parametri, e
  • il tipo restituito

(Ovvero, praticamente tutto su una funzione tranne il nome della funzione, i nomi dei parametri e il corpo.) Sospetto che non abbiano usato il termine "firma" perché ha già un significato diverso in Java — che non include il ritorno genere. Così hanno inventato un nuovo termine.

Nei linguaggi di programmazione funzionale, "tipo firma" di solito include il tipo restituito. Le firme sono utili per capire cosa potrebbe fare una funzione, quindi sono spesso scritte esplicitamente. Ad esempio, la firma (o "forma della funzione" in termini Java) per il nuovo BiFunction potrebbe essere annotata come (T, U) -> R, dove la prima parte è una tupla che rappresenta l'elenco dei parametri e la seconda parte è il tipo di ritorno.

pertanto d'accordo con this other answer: Penso che i tipi di materia e sono non scontata. Se venissero ignorati, diversi tipi definiti in tale nuovo spazio dei nomi avrebbero esattamente la stessa forma di funzione (ad esempio Supplier, Predicate, Function). Se fosse così, allora perché la documentazione dovrebbe scegliere di spiegare questi nuovi tipi con il concetto di mismatching delle forme di funzione? Non ha senso. (la risposta è stata modificata.)

Qui ci sono un altro paio di esempi di firme tipo funzionale per le nuove interfacce funzionali Java:

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

Intendevi "T, U -> R" piuttosto che "T -> U -> R"? – skomisa

+2

@skomi Sì, è (T, U) -> R, ma, per le persone che sono abituate a usare linguaggi di curring (come Haskell), sarebbe davvero T-> U-> R. –

+1

@skomi: ho rimosso quella parte della mia risposta nel frattempo. No, in realtà intendevo 'T -> U -> R', dato che i linguaggi di progrmaming funzionale di solito permettono di essere pubblicati, e io stavo parlando di programmazione funzionale in generale. Ma dal momento che il currying non è rilevante per Java, il tuo suggerimento '(T, U) -> R' sarebbe effettivamente più appropriato. Grazie per la correzione! – stakx

Problemi correlati