Scala Yield的行为与Scala Map不同

时间:2013-06-07 00:13:45

标签: arrays list scala functional-programming yield

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

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]]

我认为他们是等同的?

2 个答案:

答案 0 :(得分:4)

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

翻译成:

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

这应该有用。

Nit-picking:它们不相同,它们是相同的。 for只是糖的语法。

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

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

答案 1 :(得分:0)

澄清一下为什么你的代码无法运行,以及它实际上在做什么。

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-th 元素的通用顺序收集方法。

运行上面的代码会尝试将范围元素(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期望函数本身。

这种语言的另一个意想不到的微妙之处可能让我们感到惊讶,而我们仍然不完全熟悉它。