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ć.