Scala - 每个循环之间的差异

Sea*_*lly 10 foreach loops for-loop scala

以下两个陈述之间是否有任何区别?他们达到了同样的目的,对吗?他们编译成相同的Java代码吗?它们之间是否存在任何性能差异,还是只是偏好/可读性问题?

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

things.foreach(
  thing =>
    doSome(thing)
)
Run Code Online (Sandbox Code Playgroud)

Rex*_*err 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) } }
}
Run Code Online (Sandbox Code Playgroud)

字节码是

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
Run Code Online (Sandbox Code Playgroud)


Jör*_*tag 10

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

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

有些人已经要求甚至实施某些对象(例如Ranges)的特殊处理,但这些补丁总是被拒绝,因为特殊类型的特殊处理只会使那些特殊类型受益,而一般来说使Scala更快会受益每一个人.

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