11

以下两种说法有什么区别。他们达到了同样的目的,对吗?它们是否编译为相同的 Java 代码?它们之间是否有任何性能差异,或者仅仅是偏好/可读性的问题?

for (thing <- things) {
    doSome(thing)
}

things.foreach(
  thing =>
    doSome(thing)
)
4

4 回答 4

15

它们是相同的。给定

class Foreach {
  val things = List(1,2,3)
  def doSome(i: Int) { println(i) }
  def one { for (thing <- things) { doSome(thing) } }
  def two { things.foreach{ thing => doSome(thing) } }
}

字节码是

public void one();
  Code:
   0:   aload_0
   1:   invokevirtual   #40; //Method things:()Lscala/collection/immutable/List;
   4:   new #42; //class Foreach$$anonfun$one$1
   7:   dup
   8:   aload_0
   9:   invokespecial   #46; //Method Foreach$$anonfun$one$1."<init>":(LForeach;)V
   12:  invokevirtual   #52; //Method scala/collection/immutable/List.foreach:(Lscala/Function1;)V
   15:  return

public void two();
  Code:
   0:   aload_0
   1:   invokevirtual   #40; //Method things:()Lscala/collection/immutable/List;
   4:   new #55; //class Foreach$$anonfun$two$1
   7:   dup
   8:   aload_0
   9:   invokespecial   #56; //Method Foreach$$anonfun$two$1."<init>":(LForeach;)V
   12:  invokevirtual   #52; //Method scala/collection/immutable/List.foreach:(Lscala/Function1;)V
   15:  return
于 2013-05-24T21:52:35.200 回答
10

for理解被定义为简单的句法翻译。这非常重要,因为这允许任何对象使用for推导式,它只需要实现正确的方法。

IOW:Scala 语言规范说第一个片段被翻译成第二个片段。因此,如果这两个片段之间有任何区别,那将违反规范,因此是一个非常严重的编译器错误。

有些人要求甚至实现对某些对象(例如Ranges)的特殊处理,但这些补丁总是被拒绝,理由是对特殊类型的特殊处理只会使那些特殊类型受益,而使 Scala通常更快会受益大家。

请注意,使用宏,可能可以检测到,例如,Range纯粹作为简单 C 样式for循环的迭代,并将其转换为while循环或直接尾递归内部函数,而无需更改规范或向编译器添加特殊大小写。

于 2013-05-24T21:56:32.143 回答
1

每个scala-lang.org

与往常一样,for 表达式可以用作涉及 foreach、map、withFilter 和 flatMap 的表达式的替代语法,因此打印迭代器返回的所有元素的另一种方法是:

for (elem <- it) println(elem)

“替代语法”意味着相同。

于 2013-05-24T21:40:04.137 回答
-1

基本上

循环是一个for结构,它说

执行此操作 n。次

循环是一个foreach结构,它说

对每个值/对象执行此操作

于 2019-03-20T05:44:24.517 回答