Scala Language
Dla wyrażeń
Szukaj…
Składnia
- for {clauses} body
- for {clause} fed body
- dla treści (klauzul)
- dla (klauzul) fedruj treść
Parametry
| Parametr | Detale |
|---|---|
| dla | Wymagane słowo kluczowe do użycia pętli for / zrozumienia |
| klauzule | Iteracja i filtry, nad którymi działa for. |
| wydajność | Użyj tego, jeśli chcesz utworzyć lub „wydać” kolekcję. Korzystanie yield powoduje typ powrotnego ruchu for być zbiorem zamiast Unit . |
| ciało | Treść wyrażenia, wykonywana przy każdej iteracji. |
Basic For Loop
for (x <- 1 to 10)
println("Iteration number " + x)
To pokazuje iterację zmiennej x od 1 do 10 i zrobienie czegoś z tą wartością. Zwracanym typem tego for zrozumienia jest Unit .
Podstawowy do zrozumienia
Pokazuje to filtr w pętli for i wykorzystanie yield do stworzenia „zrozumienia sekwencji”:
for ( x <- 1 to 10 if x % 2 == 0)
yield x
Dane wyjściowe są następujące:
scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8, 10)
Zrozumienie jest przydatne, gdy trzeba utworzyć nową kolekcję na podstawie iteracji i jej filtrów.
Nested For Loop
To pokazuje, jak można iterować wiele zmiennych:
for {
x <- 1 to 2
y <- 'a' to 'd'
} println("(" + x + "," + y + ")")
(Należy pamiętać, że to tutaj jest metoda operator infix która zwraca zakres integracyjnego . Patrz definicja tutaj ).
To tworzy wynik:
(1,a)
(1,b)
(1,c)
(1,d)
(2,a)
(2,b)
(2,c)
(2,d)
Zauważ, że jest to równoważne wyrażenie, które używa nawiasów zamiast nawiasów:
for (
x <- 1 to 2
y <- 'a' to 'd'
) println("(" + x + "," + y + ")")
Aby zebrać wszystkie kombinacje w jeden wektor, możemy yield wynik i ustawić go na 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))
Monadyczny dla zrozumienia
Jeśli masz kilka obiektów typów monadycznych , możemy osiągnąć kombinacje wartości za pomocą „do zrozumienia”:
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)
Typ zwracany tego bloku to Unit .
Jeśli obiekty są tego samego typu monadycznej M (np Option ), a następnie za pomocą yield powróci obiekt typu M , a nie z 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))
Zauważ, że słowa kluczowego yield nie można użyć w oryginalnym przykładzie, w którym występuje kombinacja typów monadycznych ( Option i List ). Próba zrobienia tego spowoduje błąd niedopasowania typu kompilacji.
Iteruj przez kolekcje za pomocą pętli For
To pokazuje, jak wydrukować każdy element mapy
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
To pokazuje, jak wydrukować każdy element listy
val list = List(1,2,3)
for(number <- list) println(number) // prints 1, 2, 3
Desugaring dla zrozumienia
for pojęcia w Scali to tylko cukier składniowy . Te withFilter są realizowane za pomocą withFilter , foreach , flatMap i map ich typów tematycznych. Z tego powodu tylko typy, dla których zdefiniowano te metody, mogą być wykorzystane for zrozumienia.
A for zrozumienia następującej postaci, z wzorami pN , generatorami gN i warunkami cN :
for(p0 <- x0 if g0; p1 <- g1 if c1) { ??? }
... usunie cukier z zagnieżdżonych wywołań za pomocą funkcji withFilter i foreach :
g0.withFilter({ case p0 => c0 case _ => false }).foreach({
case p0 => g1.withFilter({ case p1 => c1 case _ => false }).foreach({
case p1 => ???
})
})
Natomiast wyrażenie for / yield następującej formy:
for(p0 <- g0 if c0; p1 <- g1 if c1) yield ???
... usunie cukier z zagnieżdżonych połączeń za pomocą withFilter i flatMap lub map :
g0.withFilter({ case p0 => c0 case _ => false }).flatMap({
case p0 => g1.withFilter({ case p1 => c1 case _ => false }).map({
case p1 => ???
})
})
(Zauważ, że map jest używana w najgłębszym rozumieniu, a flatMap jest używany w każdym zewnętrznym rozumieniu).
for zrozumienia można zastosować dowolny typ implementujący metody wymagane przez odwodnioną reprezentację. Nie ma żadnych ograniczeń dotyczących typów zwracanych tych metod, o ile można je skomponować.