将选项链接在一起的模式

时间:2014-11-11 22:36:56

标签: scala

我发现我经常需要将在Option上运行的函数链接在一起并返回一个看起来像这样的Option

if(foo.isDefined) someFunctionReturningOption(foo.get) else None

有更清洁的方法吗?对于更复杂的变量,这种模式变得非常冗长。

我在表单处理代码中看到了一些必须处理可选数据的问题。如果值为None或某些转换(可能会失败),则会插入None(如果有值)。

这非常像the ?. operator proposed for C#

4 个答案:

答案 0 :(得分:6)

您可以使用flatMap

foo.flatMap(someFunctionReturningOption(_))

或者在for-comprehension中:

for {
    f <- foo
    r <- someFunctionReturningOption(f)
} yield r

将这些函数的多个实例链接在一起时,首选for-comprehension,因为它们会降低到flatMap s。

答案 1 :(得分:4)

有很多选择(双关语意)但是对于理解,我猜,在链条的情况下是最方便的

for { 
  x <- xOpt
  y <- someFunctionReturningOption(x)
  z <- anotherFunctionReturningOption(y)
} yield z

答案 2 :(得分:2)

您正在寻找flatMap

foo.flatMap(someFunctionReturningOption)

这适用于一般的monadic结构,其中包裹类型的monad使用flatMap返回相同类型(例如flatMap上的Seq[T]返回Seq)。

答案 3 :(得分:2)

Option支持map(),因此当xOption[Int]此构造时:

if (x.isDefined)
  "number %d".format(x.get)
else
  None

更容易写为:

x map (i => "number %d".format(i))

map将保持None未修改,但它会将传递给它的函数应用于任何值,并将结果包装回Option中。例如,请注意“x”如何转换为下面的字符串消息,但“y”将作为None传递:

scala> val x: Option[Int] = Some(3)
x: Option[Int] = Some(3)

scala> val y: Option[Int] = None
y: Option[Int] = None

scala> x map (i => "number %d".format(i))
res0: Option[String] = Some(number 3)

scala> y map (i => "number %d".format(i))
res1: Option[String] = None