2014-11-06 4 views
6

Qual è il modo idiomatico di applicare una funzione A => Try[B] su un List[A] e restituire sia il primo risultato di successo Some[B] (entra in corto circuito) o se tutto fallisce, ritorna NoneScala: Prova fino primo successo in un elenco

voglio fare qualcosa di simile:

val inputs: List[String] = _ 

def foo[A, B](input: A): Try[B] = _ 

def main = { 
    for { 
    input <- inputs 
    } foo(input) match { 
    case Failure(_) => // continue 
    case Success(x) => return Some(x) //return the first success 
    } 
    return None // everything failed 
} 

risposta

7

Puoi fare la stessa cosa usando collectFirst in un solo passaggio meno:

inputs.iterator.map(foo).collectFirst { case Success(x) => x } 
+0

Domanda correlata. Cosa accadrebbe se volessi prima "Success [A]" o l'ultimo "Failure"? – pathikrit

+0

@wrick: 'val tmp = inputs.toStream.map (foo); tmp.find (_. isSuccess) oElse tmp.lastOption' – senia

5

Si desidera che questo:

inputs 
    .iterator // or view (anything lazy works) 
    .map(foo) 
    .find(_.isSuccess) 
    .map(_.get) 

restituisce un Option[B].

+0

No, lo voglio "corto circuito" vale a dire non valuta dopo il primo successo. 'foo' nel mio caso è costoso e lento e la mia lista di input è grande. – pathikrit

+0

Ecco a cosa serve '.iterator'. È anche il motivo per cui ho detto qualcosa di pigro. – Nate