Scala Language
Для выражений
Поиск…
Синтаксис
- для тела {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
понимания может применяться к любому типу, реализующему методы, требуемые де-сагированным представлением. Никаких ограничений на типы возврата этих методов не существует, если они являются составными.