Поиск…


Синтаксис

  • для тела {clauses}
  • для {clauses} результата тела
  • для (статей) тела
  • для (статей) дают тело

параметры

параметр подробности
за Требуемое ключевое слово для использования цикла / понимания for
статьи Итерация и фильтры, над которыми работает.
Уступать Используйте это, если вы хотите создать или «уронить» коллекцию. Используя yield вызовет тип возврата for быть коллекция вместо Unit .
тело Тело выражения for, выполняемое на каждой итерации.

Базовый для цикла

for (x <- 1 to 10)
  println("Iteration number " + x)

Это демонстрирует итерацию переменной x , от 1 до 10 и выполнение чего-то с этим значением. Тип возврата for понимания - Unit .

Основы для понимания

Это демонстрирует фильтр для цикла и использование yield для создания «понимания последовательности»:

for ( x <- 1 to 10 if x % 2 == 0)
  yield x

Выход для этого:

scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8, 10)

Для понимания полезно, когда вам нужно создать новую коллекцию на основе итерации и ее фильтров.

Вложенный для цикла

Это показывает, как вы можете перебирать несколько переменных:

for {
  x <- 1 to 2
  y <- 'a' to 'd'
} println("(" + x + "," + y + ")")

(Обратите внимание , что to здесь является методом инфиксного оператора , который возвращает диапазон включительно . См определения здесь .)

Это создает выход:

(1,a)
(1,b)
(1,c)
(1,d)
(2,a)
(2,b)
(2,c)
(2,d)

Обратите внимание, что это эквивалентное выражение, используя скобки вместо скобок:

for (
  x <- 1 to 2
  y <- 'a' to 'd'
) println("(" + x + "," + y + ")")

Чтобы получить все комбинации в один вектор, мы можем yield результат и установить его в val :

val a = for {
  x <- 1 to 2
  y <- 'a' to 'd'
} yield "(%s,%s)".format(x, y)
// a: scala.collection.immutable.IndexedSeq[String] = Vector((1,a), (1,b), (1,c), (1,d), (2,a), (2,b), (2,c), (2,d))

Монадический для понимания

Если у вас есть несколько объектов монадических типов, мы можем добиться сочетания значений, используя «для понимания»:

for {
   x <- Option(1)
   y <- Option("b")
   z <- List(3, 4)
} {
    // Now we can use the x, y, z variables
    println(x, y, z)
    x  // the last expression is *not* the output of the block in this case!
}

// This prints
// (1, "b", 3)
// (1, "b", 4)

Тип возврата этого блока - Unit .

Если объекты имеют один и тот же монадический тип M (например, Option ), то использование yield вернет объект типа M вместо Unit .

val a = for {
   x <- Option(1)
   y <- Option("b")
} yield {
    // Now we can use the x, y variables
    println(x, y)
    // whatever is at the end of the block is the output
    (7 * x, y)
}

// This prints:
// (1, "b")
// The val `a` is set:
// a: Option[(Int, String)] = Some((7,b))

Обратите внимание, что ключевое слово yield нельзя использовать в исходном примере, где есть сочетание монадических типов ( Option и List ). Попытка сделать это приведет к ошибке несоответствия типа компиляции.

Итерация через коллекции с использованием цикла for

Это демонстрирует, как печатать каждый элемент карты

val map = Map(1 -> "a", 2 -> "b")
for (number <- map) println(number) // prints (1,a), (2,b)
for ((key, value) <- map) println(value) // prints a, b

Это демонстрирует, как печатать каждый элемент списка

val list = List(1,2,3)
for(number <- list) println(number) // prints 1, 2, 3

Desugaring для понимания

for понимания в Scala просто синтаксический сахар . Эти понимания реализуются с использованием withFilter , foreach , flatMap и map их типов объектов. По этой причине только типы, которые имеют эти методы, могут быть использованы for понимания.

A for понимания следующей формы с образцами pN , генераторами gN и условиями cN :

for(p0 <- x0 if g0; p1 <- g1 if c1) { ??? }

... будет withFilter для вложенных вызовов, используя withFilter и foreach :

g0.withFilter({ case p0 => c0  case _ => false }).foreach({
  case p0 => g1.withFilter({ case p1 => c1  case _ => false }).foreach({
    case p1 => ???
  })
})

В то время for выражение for / yield имеет следующий вид:

for(p0 <- g0 if c0; p1 <- g1 if c1) yield ???

... будет withFilter для вложенных вызовов, используя withFilter и либо flatMap либо map :

g0.withFilter({ case p0 => c0  case _ => false }).flatMap({
  case p0 => g1.withFilter({ case p1 => c1  case _ => false }).map({
    case p1 => ???
  })
})

(Обратите внимание, что map используется во внутреннем понимании, а flatMap используется во всех внешних flatMap .)

A for понимания может применяться к любому типу, реализующему методы, требуемые де-сагированным представлением. Никаких ограничений на типы возврата этих методов не существует, если они являются составными.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow