Scala Yield的行为与Scala Map不同



我试图在一行中组合和初始化一个数组,大致相当于这样:

var characterMap = new Array[List[ActorRef]](sizeX*sizeY)
characterMap.indices.foreach(characterMap(_) = Nil)

这似乎不起作用:

var characterMap = ((0 until sizeX*sizeY) map Nil).toArray[List[ActorRef]] 

但这确实:

var characterMap = (for (_ <- 0 until sizeX*sizeY) yield Nil).toArray[List[ActorRef]]

我以为它们是等价的?

var characterMap = (for (_ <- 0 until sizeX*sizeY) yield Nil).toArray[List[ActorRef]]

翻译成:

var characterMap = (0 until sizeX*sizeY).map(_ => Nil).toArray[List[ActorRef]]

这应该有效。

吹毛求疵:它们不是等价的,它们是相同的。 for只是糖语法。

顺便说一下,您可能需要考虑:

Array.fill[List[ActorRef]](sizeX*sizeY)(Nil)

澄清一下为什么你的代码不起作用,以及它实际上在做什么。

val characterMap = ((0 until 10) map Nil)

我简化了一点,使其更易于理解。

(0 until 10) 是一个Range对象,其map方法(如其他集合等(需要类型 (A) => B
的函数在我们的案例中A = Int在哪里

由于类型检查器对map Nil感到满意,看起来Nil必须以某种方式(Int) => B函数,可以吗?

这里的重点是,Nil(i: Int)可以用作实际存在的Nil.apply(i: Int)的语法糖!

它是获取第 i 个元素的通用顺序收集方法。

运行上面的代码尝试将 range 元素(0,1,...,9)转换为 Nil 对象的相应索引值,即空List

当然,空列表中没有元素,因此会抛出错误,如图所示

scala> val characterMap = ((0 until 10) map Nil)
java.lang.IndexOutOfBoundsException: 0
    at scala.collection.LinearSeqOptimized$class.apply(LinearSeqOptimized.scala:52)
    at scala.collection.immutable.List.apply(List.scala:84)
    at scala.collection.immutable.List.apply(List.scala:84)
    at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
    at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
    at scala.collection.immutable.Range.foreach(Range.scala:141)
    at scala.collection.TraversableLike$class.map(TraversableLike.scala:244)
    at scala.collection.AbstractTraversable.map(Traversable.scala:105)
    ...

结论

yieldmap具有相同的语义含义,但语法规则略有不同。

虽然yield期望映射函数的结果,但map期望函数本身。

语言的另一个意想不到的微妙之处,当我们仍然不完全熟悉它时,它会让我们感到惊讶。

最新更新