Scala - разница между каждой петлей

Есть ли разница между двумя следующими утверждениями. Они достигают того же конца, правильно? Сопоставляют ли они один и тот же Java-код? Есть ли разница в производительности между ними или это просто вопрос предпочтения/удобочитаемости?

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

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

Ответ 1

for Постижения определяются как простые синтаксические переводы. Это чрезвычайно важно, поскольку это позволяет любому объекту работать с for -пониманиями, он просто должен реализовать правильные методы.

IOW: спецификация языка Scala говорит, что первый фрагмент переводится во второй. Таким образом, если бы между этими двумя фрагментами была какая-либо разница, это было бы нарушением спецификации и, следовательно, очень серьезной ошибкой компилятора.

Некоторые люди просили и даже реализовали специальное обращение с определенными объектами (например, Range s), но эти исправления всегда были отвергнуты с аргументом о том, что специальная обработка для специальных типов будет приносить пользу только этим специальным типам, тогда как Scala быстрее в целом принесет пользу всем.

Обратите внимание, что с помощью макросов, возможно, можно обнаружить, скажем, итерацию по сравнению с Range чисто как простой цикл C style for и преобразовать ее в цикл while или прямую внутреннюю внутреннюю функцию, без изменить спецификацию или добавить специальный компилятор в компилятор.

Ответ 2

Они идентичны. Учитывая,

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

Ответ 3

Per scala-lang.org:

Как всегда, for-выражения могут использоваться в качестве альтернативного синтаксиса для выражений, включающих foreach, map, withFilter и flatMap, поэтому еще один способ печати всех элементов, возвращаемых итератором, будет:

для (elem < - it) println (elem)

"Альтернативный синтаксис" означает идентичность.