2013-10-30 22 views
5

Per il mio primo programma Scala, sto provando a scrivere una piccola utility che convertirà un file XML da uno schema a un altro.Come restituire None in Scala

ho iniziato a scrivere un metodo che mi darà il contenuto del file:

def loadFile(filename: String, encoding: String = "utf-8"):Option[String] = { 
    try 
    { 
     val source = scala.io.Source.fromFile(filename, encoding) 
     val contents = source.mkString 
     source.close() 
     return Some(contents) 
    } 
    catch 
    { 
     return None 
    } 

    } 

Ma non viene compilato. Torno "valore apply non è un membro di Nothing" e "value isDefinedAt is not member of Nothing" come messaggi di errore dalla riga return None.

Tutti gli esempi che posso trovare restituendo un'opzione usano la corrispondenza, ma questo non ha senso qui. Voglio solo non fallire se non riesco a leggere il file per qualche motivo.

Cosa devo fare in questo caso? C'è uno schema per fare questo genere di cose in Scala?

risposta

5

C'è tutto su "catch".

a Scala si suppone di essere come questo per renderlo compilare:

def loadFile(filename: String, encoding: String = "utf-8"):Option[String] = { 
    try { 
     val source = scala.io.Source.fromFile(filename, encoding) 
     val contents = source.mkString 
     source.close() 
     Some(contents) 
    } catch { 
     case x: IOException => None 
     case x => errorHandler(x) // if any other exception 
    } 
    } 

    def errorHandler(e: Any) = None // put some logic here.. 

in modo da utilizzare:

catch { case: x:ExceptionType ={ .. handling .. }} 

In Scala catch è una funzione che accetta un'altra funzione come argomento. Quindi, avendo ciò che si lamenta, si applica la funzione. case fornisce quella funzione (PartialFunction) desiderata da catch. (In poche parole)

Nota: Tutte le eccezioni sono unchecked in Scala anche IOException.

+0

Ma concordo con + Nicolas Rinaudo sullo stile - lascia che il chiamante decida come gestire l'errore, qualunque esso sia.A volte, però, è necessario gestire alcune cose dal lato delle chiamate (come la pulizia della cache o qualsiasi altra cosa da pulire), prima di inviare nuovamente l'errore al chiamante. – ses

0

Prova questo:

def loadFile(filename: String, encoding: String = "utf-8"):Option[String] = { 
try 
{ 
    val source = scala.io.Source.fromFile(filename, encoding) 
    val contents = source.mkString 
    source.close() 
    return Some(contents) 
} 
catch 
    { 
    case e:Exception=>{ 
     return None 
    } 

    } 

}

8

In questo caso specifico (la gestione delle eccezioni), suggerirei di utilizzare un Try invece.

def loadFile(filename: String, encoding: String = "utf-8"):Option[String] = { 
    Try { 
     val source = scala.io.Source.fromFile(filename, encoding) 
     val contents = source.mkString 
     source.close() 
     return Some(contents) 
    }.toOption 
} 

Vorrei tuttavia raccomandare di non rilevare l'eccezione. Stai deglutizione la causa per l'errore con il ritorno None: è un FileNotFoundException? uno standard IOException? c'era un messaggio con l'errore (Unsupported encoding mi viene in mente ...)?

La mia regola empirica è di consentire al chiamante di gestire le eccezioni. Se lui non si preoccupa l'errore stesso, il trattamento delle cose è facile come:

Try {loadFile("test.txt")}.toOption 

Meglio ancora, dal momento che Try ha tutti i metodi richiesti, può essere utilizzato in un per-la comprensione in modo piuttosto accurato :

for(s <- Try {loadFile("test.txt")}; 
    i <- Try {s.toInt}) yield i 

Questo si tradurrà sia in un Success[Int] o un Failure che contiene un'eccezione che descrive esattamente cosa è andato storto.

Problemi correlati