在Scala中,从for循环块中返回一个值。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Scala中,从for循环块中返回一个值。相关的知识,希望对你有一定的参考价值。

在 "Scala for the impatient "一书中,第16页写道

在Scala中,一个{ }块包含一个表达式序列,结果也是一个表达式。块的值就是最后一个表达式的值。

OK,那么我们创建一个块,让块的最后一个值被赋值。

scala> val evens = for (elem <- 1 to 10 if elem%2==0) {
     |   elem
     | }
val evens: Unit = ()

我本以为 evens 至少是序列的最后一个值(即 10). 但为什么不这样做呢?

答案

Unit 是你书中所说的规则的例外。Unit 基本上说,"不管块会返回什么类型,都要忽略,因为我只打算执行块的副作用"。否则,为了让它进行类型检查,你必须在任何一个本应返回的块的末尾添加一个单位值。Unit:

val evens = for (elem <- 1 to 10 if elem%2==0) {
  elem
  ()
}

这种类型信息的浪费是人们倾向于避免在Scala中使用imperative for循环和类似的方法的原因之一。

另一答案

你需要 yield 的值,那么它就是一个for表达式。

val evens = for (elem <- 1 to 10 if elem % 2 == 0) yield elem

如果没有这一点,它只是一个语句(不返回任何东西),并被翻译为 foreach.

P.S.: 当然,这将返回所有满足谓词的元素的集合,而不是最后一个。

另一答案

当有疑问时,只需通过tyechecker来运行它,就可以窥探到它的本质。

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

在那里我们看到它返回 Unit. 您甚至可以直接在 REPL 中执行以下命令来完成这项工作

scala> :settings -Xprint:typer

而现在,你将在解释Scala表达式的同时获得实时的去ugaring。你甚至还可以更进一步,在JVM字节码中获取

scala> :javap -

For-comprehensions是Scala中最盛行的一些语法糖,所以我建议尽可能地操练它们,或许试着同时写它们的suggared和desugared from,直到它点击为止。https:/docs.scala-lang.orgtutorialsFAQyield.html

以上是关于在Scala中,从for循环块中返回一个值。的主要内容,如果未能解决你的问题,请参考以下文章

在scala for-comprehension块中执行副作用代码[重复]

scala3-for循环

16.scala的For 表达式

从python中的for循环返回值

控制结构(Scala)

就是个控制结构,Scala能有什么新花样呢?