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]
定义)。
答案 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)
Option
是Iterable
(option2Iterable
随播广告对象中存在隐式Option
方法),这就是为什么它可以在someVar <- someOption
子句中使用的原因。事实上,那个箭头意味着“从右边的集合中获取元素”。
所以你是对的,第二个例子中的name
是String
。
在第一个中,您可以看到map
上使用了Iterable
和其他Option
方法。它与下面的for
表达式基本相同,但直接调用方法,而for
只是一个语法糖,并被编译器转换为方法调用链。