2012-12-08 10 views
6

Come sviluppatore di Scala che lavora anche in GWT, accolgo con favore l'aggiunta di Optional a Guava.Unwrapping a Guava Facoltativo in una singola espressione

Uno dei nostri casi di utilizzo più comuni di Optional è quando restituzione di valori opzionali dai metodi (come suggerito dalla risposta a What's the point of Guava's Optional class

In Scala, ho spesso scrivere codice in questo modo:.

def someExpensiveOperation(params: Type): Option[ResultType] = ... 
someExpensiveOperation(params).foreach({ val => 
    doSomethingWithVal (val) 
}) 

Opzione di Guava non sembra permettere qualcosa di più elegante di qualcosa di simile:

Optional<MyType> optionalResponse = someExpensiveOperation(params); 
if (optionalResponse.isPresent()) { 
    doSomethingWithVal(optionalResponse.get()) 
} 

La variabile locale è re dundant, e richiede la ripetizione di uno schema che potrebbe essere astratto (il if (optional.isPresent()) { doSomethingWith(optional.get()) }).

L'altra opzione sarebbe quella di chiamare il metodo che restituisce un Optional due volte:

if (someExpensiveOperation(params).isPresent()) { 
    doSomethingWithVal(someExpensiveOperation(params).get()) 
} 

Ma questo è chiaramente indesiderabile, in quanto invocato un'operazione costosa più volte inutilmente.

Sono curioso di sapere come altre persone hanno gestito questo caso molto comune (forse scrivendo un metodo di utilità statico come <T>useIfPresent(Optional<T> val, Closure<? super T> closure)?) O se qualcuno ha trovato soluzioni più eleganti.

Inoltre, se qualcuno sa perché un metodo come Optional.foreach(Closure<? super T> closure) (ma si spera meglio chiamato) è stato omesso, sarei curioso di sentire la logica.

risposta

7

Non è lì perché riteniamo che l'anonimo goffo della classe di scrivere una chiusura sia più imbarazzante e meno leggibile - almeno in Java, non necessariamente in Scala - rispetto alla variabile locale e all'istruzione if che hai già scritto.

Detto questo, un'altra alternativa è

for (Foo x : someExpensiveOperation().asSet()) { 
    // do stuff with x 
} 

noti che asSet è necessario qui - Optional deliberatamente per sè non implementare Iterable.

+2

Un piccolo OT, ma mi chiedo perché 'Optional.asSet()' restituisce 'Set' invece di' ImmutableSet' poiché è documentato restituire uno immutabile. È perché 'Optional' è spedito in' c.g.c.base' e ​​non in 'c.g.c.collect'? – Xaerxess

+1

Questo è esattamente. (Il sistema di compilazione di Google più o meno vieta le dipendenze dei pacchetti ciclici.) –

+0

Questo è perfettamente ragionevole. Spesso lotto con il conflitto intrinseco tra il fare cose in quello che sembra un modo funzionale e pulito, e la mancanza di chiusure di Java. Detto questo, io uso IntelliJ che collassa automaticamente le classi interne anonime nella sintassi di chiusura in stile 8 JDK. In base a queste linee, ci sono piani per rivisitare le decisioni di progettazione basate sulla verbosità di classe anonima quando Java 8 è più vicino alla spedizione? –

Problemi correlati