Revisione Java 8 Stream
progettazione API, sono rimasto sorpreso dalla invarianza generica sulle Stream.reduce()
argomenti:Quali sono i buoni motivi per scegliere l'invarianza in un'API come Stream.reduce()?
<U> U reduce(U identity,
BiFunction<U,? super T,U> accumulator,
BinaryOperator<U> combiner)
Una versione apparentemente più versatile della stessa API potrebbe essere applicato covarianza/controvarianza sui singoli riferimenti a U
, come ad come:
<U> U reduce(U identity,
BiFunction<? super U, ? super T, ? extends U> accumulator,
BiFunction<? super U, ? super U, ? extends U> combiner)
Ciò consentirebbe il seguente, che non è possibile, attualmente:
// Assuming we want to reuse these tools all over the place:
BiFunction<Number, Number, Double> numberAdder =
(t, u) -> t.doubleValue() + u.doubleValue();
// This currently doesn't work, but would work with the suggestion
Stream<Number> stream = Stream.of(1, 2L, 3.0);
double sum = stream.reduce(0.0, numberAdder, numberAdder);
Soluzione, utilizzare metodo riferimenti a "costringere" i tipi nel tipo di destinazione:
double sum = stream.reduce(0.0, numberAdder::apply, numberAdder::apply);
C# non hanno questo problema particolare, come Func(T1, T2, TResult)
è definito come segue, utilizzando varianza dichiarazione loco, il che significa che ogni API utilizzando Func
ottiene questo comportamento gratuitamente:
public delegate TResult Func<in T1, in T2, out TResult>(
T1 arg1,
T2 arg2
)
Quali sono i vantaggi (e possibilmente, le ragioni per le decisioni EG) del progetto esistente sopra il disegno suggerito?
O, ha chiesto in modo diverso, quali sono gli avvertimenti del design suggerito che io possa essere vista (ad esempio di tipo difficoltà di inferenza, vincoli parallelizzazione, o vincoli specifici per l'operazione di riduzione, come ad esempio l'associatività, anticipazione di un futuro declaration- di Java varianza del sito su BiFunction<in T, in U, out R>
, ...)?
I sospetto che ci sarebbe un tipo di inferenza più difficile in quanto sospetto che questo lascerebbe alcuni tipi irrisolvibili senza essere espliciti (sconfiggendo il punto di inferenza) –
@PeterLawrey: Anche questa era la mia preoccupazione, ma 1) puoi provarlo? :) 2) Scala conosce 'TraversableOnce.reduce [A1>: A] (op: (A1, A1) ⇒ A1): A1' –
Un modo sarebbe scrivere un'API come questa e vedere cosa succede quando provi ad usare esso. –