在 Scala 中从 for 循环块返回一个值
In Scala returning a value from a for loop block
在书 "Scala for the impatient" 中,第 16 页说
In Scala, a { } block contains a sequence of expressions, and the
result is also an expression. The value of the block is the value of
the last expression.
OK,那我们来创建一个区块,让区块的最后一个值赋值:
scala> val evens = for (elem <- 1 to 10 if elem%2==0) {
| elem
| }
val evens: Unit = ()
我本以为 evens
至少是序列的最后一个值(即 10
)。但为什么不呢?
您需要 yield
值,然后它是一个 for 表达式:
val evens = for (elem <- 1 to 10 if elem % 2 == 0) yield elem
如果没有它,它只是一个语句(不 return 任何东西)并被翻译成 foreach
。
P.S.: 当然这将 return 满足谓词的所有元素的集合,而不是最后一个。
如有疑问,只需 运行 通过类型检查器查看幕后情况
scala -Xprint:typer -e 'val evens = for (elem <- 1 to 10 if elem%2==0) { elem }'
揭示
val evens: Unit =
scala.Predef
.intWrapper(1)
.to(10)
.withFilter(((elem: Int) => elem.%(2).==(0)))
.foreach[Int](((elem: Int) => elem))
我们看到 foreach
是链中的最后一步,它的签名是
def foreach[U](f: A => U): Unit
我们在哪里看到它 returns Unit
。您甚至可以通过执行以下命令直接从 REPL 中执行此操作
scala> :settings -Xprint:typer
现在您将在解释 Scala 表达式的同时获得实时脱糖。您甚至可以更进一步,获取 JVM 字节码本身
scala> :javap -
For-comprehensions 是 Scala 中一些最普遍的语法糖,所以我建议尽可能多地练习它们,也许尝试同时在它们的 suggared 和 desugared from 中编写它们,直到它点击: https://docs.scala-lang.org/tutorials/FAQ/yield.html
Unit
是您书中所述规则的例外。 Unit
基本上说 "ignore whatever type the block would have returned because I only intended to execute the block for the side effects." 否则,为了让它进行类型检查,你必须在任何应该 return [=11= 的块的末尾添加一个单位值]:
val evens = for (elem <- 1 to 10 if elem%2==0) {
elem
()
}
这种类型信息的丢弃是人们倾向于在 Scala 中避免命令式 for 循环和类似循环的原因之一。
在书 "Scala for the impatient" 中,第 16 页说
In Scala, a { } block contains a sequence of expressions, and the result is also an expression. The value of the block is the value of the last expression.
OK,那我们来创建一个区块,让区块的最后一个值赋值:
scala> val evens = for (elem <- 1 to 10 if elem%2==0) {
| elem
| }
val evens: Unit = ()
我本以为 evens
至少是序列的最后一个值(即 10
)。但为什么不呢?
您需要 yield
值,然后它是一个 for 表达式:
val evens = for (elem <- 1 to 10 if elem % 2 == 0) yield elem
如果没有它,它只是一个语句(不 return 任何东西)并被翻译成 foreach
。
P.S.: 当然这将 return 满足谓词的所有元素的集合,而不是最后一个。
如有疑问,只需 运行 通过类型检查器查看幕后情况
scala -Xprint:typer -e 'val evens = for (elem <- 1 to 10 if elem%2==0) { elem }'
揭示
val evens: Unit =
scala.Predef
.intWrapper(1)
.to(10)
.withFilter(((elem: Int) => elem.%(2).==(0)))
.foreach[Int](((elem: Int) => elem))
我们看到 foreach
是链中的最后一步,它的签名是
def foreach[U](f: A => U): Unit
我们在哪里看到它 returns Unit
。您甚至可以通过执行以下命令直接从 REPL 中执行此操作
scala> :settings -Xprint:typer
现在您将在解释 Scala 表达式的同时获得实时脱糖。您甚至可以更进一步,获取 JVM 字节码本身
scala> :javap -
For-comprehensions 是 Scala 中一些最普遍的语法糖,所以我建议尽可能多地练习它们,也许尝试同时在它们的 suggared 和 desugared from 中编写它们,直到它点击: https://docs.scala-lang.org/tutorials/FAQ/yield.html
Unit
是您书中所述规则的例外。 Unit
基本上说 "ignore whatever type the block would have returned because I only intended to execute the block for the side effects." 否则,为了让它进行类型检查,你必须在任何应该 return [=11= 的块的末尾添加一个单位值]:
val evens = for (elem <- 1 to 10 if elem%2==0) {
elem
()
}
这种类型信息的丢弃是人们倾向于在 Scala 中避免命令式 for 循环和类似循环的原因之一。