2011-10-17 12 views
19

Ho letto e sperimentato la versione di prova di Scala 2.9 ... cattura, e mi ha fatto pensare alle possibilità. Cosa dovrei effettivamente usare per non salvare un paio di righe di codice?Quali sono i casi d'uso per il tentativo di Scala 2.9 ... prendere la generalizzazione?

Scala 2.9 Final Release Notes

+0

Non sono sicuro che lo userei .... ma puoi usare * qualsiasi * (conforme) PartialFunction ... avere un errore unificato per la gestione altrove? (Dite "ignoreTheseSillyClosableExceptions".) Inoltre, "è proprio bello" che Scala possa esprimerlo così ;-) –

+0

Per ispirazione: Paul Phillips ha fornito un esempio motivazionale quando ha implementato questo: http://www.scala-lang.org/node/8070 –

+3

La domanda sarebbe meglio con un esempio o almeno un collegamento. – ziggystar

risposta

24

Il caso d'uso è quello di essere in grado di avere la gestione generica in tutta l'applicazione di errore. Supponiamo che tu voglia gestire tutti gli FileNotFoundException s nell'applicazione inviando un'e-mail a un amministratore. In precedenza, dovreste fare in questo modo:

// Globally 
val fileNotFound: PartialFunction[Throwable, Unit] = { 
    case e: FileNotFoundException => 
    // Create report and send the e-mail 
} 

// On each try-catch-block 
try { 
    // Open file 
} 
catch { 
    case fnf: FileNotFoundException => fileNotFound(fnf) 
} 

Ora basta fare:

try { 
    // Open file 
} catch fileNotFound 

Questo ha anche il bel vantaggio che è possibile collegare diversi gestori di tale eccezione con il metodo orElse su funzioni parziali:

val fileErrors = fileNotFound orElse endOfFile orElse invalidFormat 

E quindi basta utilizzarlo ovunque, dove è necessario il trattamento delle eccezioni del file. Tale gestore di errori può essere combinato dinamicamente in base al file di configurazione dell'applicazione, ad esempio. Questo è molto meno ingombrante del modello che corrisponde ovunque e chiama il gestore corretto.

Una cosa utile che può essere sfruttata sopra funzioni parziali è l'operatore andAlso, che funge da operatore di sequenziamento su due funzioni parziali. Ciò sarebbe utile quando si desidera eseguire una gestione degli errori specifica per un blocco try-catch specifico dopo aver eseguito la gestione degli errori generici.

implicit def pf2ops(pf: PartialFunction[Throwable, Unit]) = new { 
    def andAlso(localpf: PartialFunction[Throwable, Unit]) = new PartialFunction[Throwable, Unit] { 
    def apply(t: Throwable) = { 
     if (pf.isDefinedAt(t)) pf(t) 
     localpf(t) 
    } 
    def isDefinedAt(t: Throwable) = pf.isDefinedAt(t) || localpf.isDefinedAt(t) 
    } 
} 

E poi si può fare questo:

scala> try { 
    | throw new java.io.FileNotFoundException 
    | } catch fnf andAlso { 
    | case e: Exception => println("I don't know, but something is specific to this particular block.") 
    | } 
I don't know, but something is specific to this particular block. 

Credo che si potrebbe giocare ulteriormente con la semantica esatte e il significato (e il nome) di andAlso.

+0

Bella risposta - Penso che la parte di andAlso era il bit che mi mancava. – Seth

7

Buona risposta per axel22, ma penso che la vera ragione della sua introduzione sia un'altra cosa. La manipolazione try/ha introdotto un caso speciale . Hai usato una funzione parziale letterale, ma non puoi realmente sostituirla con una funzione parziale. Ora, catch riceve solo una funzione parziale e un altro caso speciale nella lingua non esiste più.

+0

Anche a me piace questa risposta :) – Seth

+0

Questo in realtà conferma il mio ragionamento iniziale: questa è principalmente una funzione di "ordinata". – Seth

+0

Concordato - è il principio di uniformità al suo meglio - un costrutto generalizzato che ha come conseguenza l'usabilità. – axel22

Problemi correlati