两个新手问题。
似乎for
理解了解Options
并且可以自动跳过None
并解开Some
,例如
val x = Map("a" -> List(1,2,3), "b" -> List(4,5,6), "c" -> List(7,8,9))
val r = for {map_key <- List("WRONG_KEY", "a", "b", "c")
map_value <- x get map_key } yield map_value
输出:
r: List[List[Int]] = List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9))
Options
去哪儿了?有人可以说明这是如何工作的?我们可以一直依赖这种行为吗?
第二件事是为什么这不编译?
val x = Map("a" -> List(1,2,3), "b" -> List(4,5,6), "c" -> List(7,8,9))
val r = for {map_key <- List("WRONG_KEY", "a", "b", "c")
map_value <- x get map_key
list_value <- map_value
} yield list_value
它给出了
Error:(57, 26) type mismatch;
found : List[Int]
required: Option[?]
list_value <- map_value
^
查看第一个示例的类型,我不确定为什么我们需要Option
?
答案 0 :(得分:1)
因为理解被转换为对map或flatMap调用序列的调用。见here
您的for
循环等同于
List("WRONG_KEY", "a", "b", "c").flatMap(
map_key => x.get(map_key).flatMap(map_value => map_value)
)
flatMap
中的 Option
定义为
@inline final def flatMap[B](f: A => Option[B]): Option[B]
因此,不允许传递List
作为参数,因为编译器会通知您。
答案 1 :(得分:1)
我认为差异是由于在Seq特征中将理解扩展为map()和flatMap方法调用的方式。
为简明起见,我们定义一些变量:
var keys = List("WRONG_KEY", a, b, c)
您的第一个案例相当于:
val r = keys.flatMap(x.get(_))
而你的第二个案例相当于:
val r= keys.flatMap(x.get(_).flatMap{ case y => y })
我认为问题是Option.flatMap()应该返回一个Option [],这在第一种情况下很好,但在第二种情况下与x.get()。flatMap的传递不一致,这是一个List [Int]。
这些理解翻译规则在Wampler&amp; Sons的“Programming Scala”的第7章中有更详细的解释。佩恩。
答案 2 :(得分:1)
也许这个小差异,设置括号和调用flatten,说清楚:
scala> List("WRONG_KEY", "a", "b", "c").map (x get _)
res81: List[Option[List[Int]]] = List(None, Some(List(1, 2, 3)), Some(List(4, 5, 6)), Some(List(7, 8, 9)))
scala> List("WRONG_KEY", "a", "b", "c").map (x get _).flatten
res82: List[List[Int]] = List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9))
这相当于:
path
中间值(map_key)在第二个块中消失为_。
答案 3 :(得分:1)
您正在for语句中混合两个不同的monad(List
和Option
)。这有时按预期工作,但并非总是如此。无论如何,您可以自己将选项转换为列表:
for {
map_key <- List("WRONG_KEY", "a", "b", "c")
list_value <- x get map_key getOrElse Nil
} yield list_value