2011-12-16 71 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 

但这些都不似乎是您的情况