为了理解地图,我对幕后打字感到困惑.我的理解是外部集合类型通常应该被保留,我们在以下两种情况下看到预期的行为:
scala> for { | (k,v) <- Map(0->1,2->3) | } yield k -> v res0: scala.collection.immutable.Map[Int,Int] = Map(0 -> 1,2 -> 3) scala> for { | (k,2->3) | foo = 1 | } yield k -> v res1: scala.collection.immutable.Map[Int,2 -> 3)
但是当我在for comprehension中添加第二个作业时,我得到了一些令人惊讶的东西:
scala> for { | (k,2->3) | foo = 1 | bar = 2 | } yield k -> v res2: scala.collection.immutable.Iterable[(Int,Int)] = List((0,1),(2,3))
为什么会这样?
解决方法
如果您运行scala -Xprint:typer -e“for {…} yield k-> v”,您可以获得代码的去糖化版本.这是你得到的非常简化的版本:
val m: Map[Int,Int] = Map(0->1,2->3) m.map { case x @ (k,v) => val foo = 1 val bar = 2 (x,foo,bar) }.map { case ((k,v),bar) => (k,v) }
所以你会注意到,当for-comprehension转换为.map调用时,它实际上返回foo和bar以及k-> v,这意味着它是一个Tuple3 [(Int,Int),Int,Int ].由于Tuple3对象的可迭代不能转换为Map,因此它假定它必须返回Iterable.但是,为了获得正确的输出,它是Tuple2对象的集合,它执行一个从Tuple3中丢弃foo和bar的辅助.map,但此时它不再知道它应该是一个Map,因为当你链接到.map的调用,信息不会被结转.
只有一个赋值的例子很幸运,因为中间表示是Tuple2 [(Int,Int].
另一方面,如果直接使用.map,它可以工作:
Map(0->1,2->3).map { case (k,v) => val foo = 1 val bar = 2 k -> v }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。