为什么这两个代码块与Option类相同?

时间:2013-05-11 19:26:29

标签: scala scala-option

In documentation of Option class写了以下两个例子是等价的:

val name: Option[String] = request getParameter "name"
val upper = name map { _.trim } filter { _.length != 0 } map { _.toUpperCase }
println(upper getOrElse "")

val upper = for {
  name <- request getParameter "name"
  trimmed <- Some(name.trim)
  upper <- Some(trimmed.toUpperCase) if trimmed.length != 0
} yield upper
println(upper getOrElse "")

但是我不明白它们是如何等价的:在第一个代码块request getParameter "name"中返回类型为Option[String]的实例,但在第二个代码块语句name <- request getParameter "name"中返回类型为{的实例{1}}(我认为是因为String变量上的trim方法调用了name方法(trim没有为Option[String]定义)。

2 个答案:

答案 0 :(得分:5)

for ... yield理解到map / flatMap方法调用的转换由编译器完成。 Option不是Iterable;在这种情况下唯一需要的是Option map / flatMap方法:

  • flatMap如果在同一->块中有更多for次来电话
  • map如果是最后一个

我们可以像这样创建自己的MyOption类:

case class MyOption[+T](value: T) {
  def flatMap[A](f: T => MyOption[A]): MyOption[A] = f(value)
  def map[A](f: T => A): MyOption[A] = MyOption(f(value))
  override def toString = s"Some($value)"
}

然后:

val result = for {
  a <- MyOption("one")
  b <- MyOption("two")
} yield a + "," + b
println(result)
// prints: Some(one,two)

答案 1 :(得分:1)

OptionIterableoption2Iterable随播广告对象中存在隐式Option方法),这就是为什么它可以在someVar <- someOption子句中使用的原因。事实上,那个箭头意味着“从右边的集合中获取元素”。

所以你是对的,第二个例子中的nameString

在第一个中,您可以看到map上使用了Iterable和其他Option方法。它与下面的for表达式基本相同,但直接调用方法,而for只是一个语法糖,并被编译器转换为方法调用链。