【问题标题】:Scala Yield behaves differently than Scala MapScala Yield 的行为与 Scala Map 不同
【发布时间】:2013-06-03 04:20:31
【问题描述】:

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

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

我认为它们是等价的?

【问题讨论】:

    标签: arrays list scala functional-programming yield


    【解决方案1】:

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

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

    为了更容易理解,我做了一些简化。

    (0 until 10) 是一个Range 对象,其map 方法(对于其他集合等)需要(A) =&gt; B 类型的函数
    在我们的例子中A = Int

    既然类型检查器对map Nil 很满意,那么看起来Nil 在某种程度上肯定是一个函数(Int) =&gt; B,会不会?

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

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

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

    该语言的另一个意想不到的微妙之处可能会让我们感到惊讶,而我们还没有完全熟悉它。

    【讨论】:

    • 有趣!实际上,我什至没有考虑过Nil 会作为一个函数工作,但考虑到(1 :: Nil)(0) 可以工作,这是有道理的。 “虽然yield 期望映射函数的结果,但map 期望函数本身。”
    【解决方案2】:
    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)
    

    【讨论】:

    • 我没有意识到 Nil_=&gt;Nil 会有所不同!我在找Array.fill,但java.utils.Arrays.fill 不太一样;)非常感谢。
    猜你喜欢
    • 1970-01-01
    • 2016-07-21
    • 2013-07-15
    • 2016-11-05
    • 2018-02-20
    • 1970-01-01
    • 2010-11-06
    • 2014-05-10
    • 1970-01-01
    相关资源
    最近更新 更多