【问题标题】:scala yield gives unexpected resultscala产量给出了意想不到的结果
【发布时间】:2016-12-17 20:18:27
【问题描述】:

我尝试遵循两个版本的代码来了解 scala 中的 yield 是如何工作的。我无法理解为什么我会得到两个不同的结果

在这个版本中,我调用yield,表达式只是乘以2。我得到一个2的第一个10倍的向量。这对我来说很有意义

scala> val r = for (j <- 1 to 10) yield {
     | (j*2).toString //multiply by 2
     | }
r: scala.collection.immutable.IndexedSeq[String] = Vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20) // got multiples of 2. This looks ok

有趣的是,在这个版本中,我所做的只是将乘以 2 的结果存储在一个 val 中。但现在我得到一个空向量!这是为什么呢?

scala> val r = for (j <- 1 to 10) yield {
     | val prod = (j*2).toString //multiply by 2 but store in a val
     | }
r: scala.collection.immutable.IndexedSeq[Unit] = Vector((), (), (), (), (), (), (), (), (), ())  //this is empty

我认为 val prod = (j*2).toString 可能会导致 Unit 结果,但是当我尝试在 scala 解释器上遵循独立表达式时,我可以看到 prod 是一个字符串

scala> val prod = 2.toString()
prod: String = 2

【问题讨论】:

  • 你需要从lamba返回一些东西——你的lambda不返回任何东西——因此它是一个void类型或Scala中的Unit。在val之后的一行添加prod,它会隐式返回。
  • @BoristheSpider 是对的。 val prod 被创建和放弃了 10 次,所以 yield 在每次迭代后都没有任何东西可以产生。
  • 换一种说法,prod 确实是一个字符串,但val prod = ... 的类型是Unit。所以第二个例子中的 Vector 是 Vector[Unit] 类型。
  • 在你的第二个语句中,你需要在最后一行之后添加prod 以作为返回值。您在最后一行所做的只是设置一个值但不返回任何内容,因此输出 Unit

标签: scala yield


【解决方案1】:

在 Scala 中,每个表达式都会返回一些东西。但是出于性能原因,分配被设计为返回Unit(请参阅What is the motivation for Scala assignment evaluating to Unit rather than the value assigned?)。

在你的 sn-p 中,在最后一个例子中 REPL 说 prod: String = 2,这意味着 prod 有一些价值,这是为了你的方便。但是试试{ val prod = 2.toString() }:

scala> { val prod = 2.toString() }

scala> println(res0)
()

()Unit 类型唯一可能的值。

(我不知道为什么res0 在第一次点赞后没有显示,因为 REPL 中类似resN 的值会收集所有未明确分配的结果)

【讨论】:

    猜你喜欢
    • 2019-05-19
    • 2017-01-05
    • 2021-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-17
    • 2021-04-22
    • 2016-02-13
    相关资源
    最近更新 更多