2013-10-30 64 views
5

對於我的第一個Scala程序,我試圖編寫一個小實用程序,它將XML文件從一個模式轉換爲另一個模式。如何在Scala中返回None

我開始寫這會給我的文件內容的方法:

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 
    } 

    } 

不過,這並不編譯。我從return None行返回「value apply不是Nothing的成員」和「value isDefinedAt不是Nothing的成員」作爲錯誤消息。

我能找到的所有例子都返回一個Option使用匹配,但這裏沒有意義。我只是想不會因爲某些原因無法讀取文件而失敗。

在這種情況下該怎麼辦? Scala中有這樣一種模式嗎?

回答

5

全部關於"catch"

在Scala中它應該是這樣的,使其編譯:

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

所以使用:

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

在斯卡拉catch是接受另一個函數作爲參數的函數。所以有了你會抱怨應用函數。 case提供了catch想要的函數(PartialFunction)。 (在堅果殼)

注:所有的例外是在unchecked甚至ScalaIOException

+0

但我同意+ Nicolas Rinaudo關於這種風格 - 讓調用者決定如何處理錯誤,無論它是什麼。但是,有時候,你需要在調用方處理一些東西(比如清理緩存或者其他需要清理的東西),然後再將錯誤發回給調用者。 – ses

0

試試這個:

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

在這種特殊情況下(異常處理),我建議使用Try代替。

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 
} 

但是,我會建議不要捕捉異常。您正在通過返回None來解決錯誤原因:是FileNotFoundException?標準IOException?是否有錯誤消息(Unsupported encoding想到...)?

我的經驗法則是讓調用者處理異常。如果他不關心錯誤本身,搬運東西一樣簡單:

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

更妙的是,因爲Try擁有所有必需的方法,它可以在一個換理解在一個相當簡潔的方式使用:

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

這將導致在任何一個Success[Int]或包含準確描述出了什麼問題異常的Failure