2013-10-30 22 views
5

Für mein erstes Scala-Programm versuche ich ein kleines Dienstprogramm zu schreiben, das eine XML-Datei von einem Schema in ein anderes konvertiert.So geben Sie None in Scala zurück

Ich begann ein Verfahren zu schreiben, die mir den Inhalt der Datei geben:

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 
    } 

    } 

Aber es funktioniert nicht kompilieren. Ich bekomme zurück "Wert anwenden ist kein Mitglied von Nothing" und "Wert isDefinedAt ist kein Mitglied von Nothing" als Fehlermeldungen aus der Zeile return None.

Alle Beispiele, die ich finden kann, die eine Option zurückbringen, verwenden das Zusammenbringen, aber das macht hier keinen Sinn. Ich möchte einfach nicht versagen, wenn ich die Datei aus irgendeinem Grund nicht lesen kann.

Was soll ich in diesem Fall tun? Gibt es ein Muster dafür in Scala?

Antwort

5

Es gibt alles über "catch".

In scala es soll so sein, um es zu kompilieren:

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

In Scala catch eine Funktion, die eine andere Funktion als Argument akzeptiert:

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.. 

So verwenden. Also, was Sie haben, würde sich beschweren über die Funktion anwenden. case bietet diese Funktion (PartialFunction), die catch will. (In Kürze)

Hinweis: Alle Ausnahmen sind unchecked in Scala sogar IOException.

+0

Aber ich stimme mit + Nicolas Rinaudo über den Stil - lassen Sie Anrufer entscheiden, wie mit Fehler umzugehen, was auch immer es ist.Manchmal müssen Sie jedoch einige Dinge auf der Seite des Anrufers behandeln (wie zum Beispiel den Cache säubern oder was auch immer zu säubern ist), bevor Sie den Fehler an den Anrufer zurücksenden. – ses

0

Try this:

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 diesem speziellen Fall (Exception Handling), würde ich vorschlagen, eine Try stattdessen verwenden.

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 
} 

Ich würde jedoch empfehlen, die Ausnahme überhaupt nicht zu fangen. Sie schlucken die Ursache für den Fehler, indem Sie None zurückgeben: ist es ein FileNotFoundException? ein Standard IOException? War da eine Nachricht mit dem Fehler (Unsupported encoding kommt mir in den Sinn ...)?

Meine Faustregel ist, den Anrufer mit Ausnahmen umgehen zu lassen. Wenn er nicht über den Fehler schert sich die Dinge Handhabung ist so einfach wie:

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

Noch besser wäre es, da Try alle erforderlichen Methoden hat, kann es in einem für Verständnis in einer ziemlich nette Art und Weise verwendet werden, :

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

Dies entweder ein Success[Int] oder ein Failure führen wird, die eine Ausnahme genau beschreibt, enthält das, was schief gelaufen ist.

Verwandte Themen