2011-12-16 46 views
0

我有一個Scala的Option[T]。如果該值Some(x)我想用一個不返回值(Unit)過程來處理它,但如果是None,我想打印一個錯誤。處理Scala的選項[T]

我可以使用下面的代碼要做到這一點,但我明白,更習慣的方法是治療Option[T]作爲一個序列,並使用mapforeach,等我該怎麼辦呢?

opt match { 
    case Some(x) => // process x with no return value, e.g. write x to a file 
    case None => // print error message 
} 
+3

你可能想看看[Tony Morris'scala.Option Cheat Sheet](http://blog.tmorris.net/scalaoption-cheat-sheet/) – 2011-12-16 17:50:37

+0

鏈接已變成http://blog.tmorris .net/posts/scalaoption-cheat-sheet/index.html – giampaolo 2014-02-13 20:59:06

回答

3

Scala的Option是,可悲的是,缺少一個方法做的正是這種。我想補充一個:

class OptionWrapper[A](o: Option[A]) { 
    def fold[Z](default: => Z)(action: A => Z) = o.map(action).getOrElse(default) 
} 
implicit def option_has_utility[A](o: Option[A]) = new OptionWrapper(o) 

它具有略微更好的(在我看來)使用

op.fold{ println("Empty!") }{ x => doStuffWith(x) } 

你可以從它是如何定義的map/getOrElse可以用來代替模式匹配看到。

或者,Either已經有一個fold方法。所以,你可以

op.toRight(()).fold{ _ => println("Empty!") }{ x => doStuffWith(x) } 

但是這是一個有點笨拙因爲你必須提供左值(這裏(),即單位),然後定義一個函數,而不是僅僅說明你要對發生的事情None

模式匹配也不錯,特別是對於較長的代碼塊。對於短小的比賽來說,比賽的開銷會影響到比賽的重點。例如:

op.fold{ printError }{ saveUserInput } 

已經少了很多語法開銷比

op match { 
    case Some(x) => saveUserInput(x) 
    case None => printError 
} 

,因此,一旦你希望它是一個更容易理解。

3

我建議你簡單地和安全地使用opt.get本身拋出一個NoSuchElementException異常,如果optNone。或者,如果你想拋出自己的異常,你可以這樣做:

val x = opt.getOrElse(throw new Exception("Your error message")) 
// x is of type T 
+0

我不想拋出錯誤信息。我只需要打印一個錯誤,以標準錯誤。我想我可以把所有的東西都包裝起來,但這看起來好像過火了。 – Ralph 2011-12-16 17:54:42

+0

是的,嘗試抓住將是最好的策略。您可以將所有與文件寫入相關的代碼包裝在try塊中,或者更好地將其分解爲某種方法。還請注意我的答案的更新。 – 2011-12-16 18:01:34

6

我想明確的模式匹配最適合您的使用案例。

2

模式匹配是這裏最好的選擇。

不過,如果你想治療方案的序列,並繪製了它,你可以做到這一點,因爲該股的值:

opt map { v => 
    println(v) // process v (result type is Unit) 
} getOrElse { 
    println("error") 
} 

順便說一句,打印一個錯誤是某種「反模式」,所以最好反正拋出一個異常:

opt.getOrElse(throw new SomeException) 
2

爲@missingfaktor說,你是在模式匹配給最可讀的結果的確切情況。 如果Option有一個值你想做點什麼,如果沒有,你想做點別的。

雖然有各種方式來使用地圖和其他功能結構期權類型,當他們一般都是有用:

您要使用的一些情況,並如忽略無申訴案你的情況

opt.map(writeToFile(_)) //(...if None just do nothing) 

,或者你想鏈運作上有多個選項,只給一個結果,當所有的人都有些。舉例來說,這樣做的一個方法是:

val concatThreeOptions = 
for { 
    n1 <- opt1 
    n2 <- opt2 
    n3 <- opt3 
} yield n1 + n2 + n3 // this will be None if any of the three is None 
        // we will either write them all to a file or none of them 

但這些都不似乎是您的情況