19.3. Przekształcenia pętli i wyrażenia for
Dokładne znaczenie używanych w pętli i wyrażeniu for generatorów i dozorów jest zdefiniowane przez zasady przekształcania pętli i wyrażenia for na wywołania metod map, withFilter, flatMap i foreach. Pętle i wyrażenia for mogą być przekształcone na wyrażenia zawierające wywołania wszystkich lub niektórych ze wspomnianych metod. Ilustrują to poniższe przykłady.
Pętli for niezawierającej słowa kluczowego yield odpowiada wyrażenie zawierające wywołanie metody foreach. Następującej pętli for
scala> for (x <- List(1,2,3)) println(x) 1 2 3
odpowiada wyrażenie
scala> List(1,2,3).foreach{ case x => println(x) } 1 2 3
Wyrażeniu for zawierającemu słowo kluczowe yield odpowiada wyrażenie zawierające wywołanie metody map. Następującemu wyrażeniu for
scala> for (x <- List(1,2,3)) yield x*x res2: List[Int] = List(1, 4, 9)
odpowiada wyrażenie
scala> List(1,2,3).map{ case x => x*x } res3: List[Int] = List(1, 4, 9)
Teraz powinno stać się zrozumiałe dlaczego wyrażenia for z poprzedniego punktu zachowywały rodzaj zwracanej kolekcji. Powyższemu wyrażeniu for odpowiada wywołanie metody map na użytej w generatorze kolekcji. Metoda map wywołana na liście zwraca również listę, a wywołana na tablicy zwraca tablicę. Poniższe wyrażenia są również swoimi odpowiednikami i oba zwracają w wyniku tablicę liczb typu Int.
scala> for (x <- Array(1,2,3)) yield x*x res4: Array[Int] = Array(1, 4, 9) scala> Array(1,2,3).map{ case x => x*x } res5: Array[Int] = Array(1, 4, 9)
Wyrażeniu for zawierającemu dwa generatory odpowiada wyrażenie zawierające wywołanie metody flatMap. Następujące dwa wyrażenia są swoimi odpowiednikami.
scala> for (x <- Array(1,2,3); y <- Array(4,5)) yield x*y res6: Array[Int] = Array(4, 5, 8, 10, 12, 15) scala> Array(1,2,3).flatMap{ case x => Array(4,5).map{ case y => x*y }} res7: Array[Int] = Array(4, 5, 8, 10, 12, 15)
Wyrażeniu for zawierającemu generator, po którym występuje dozór, odpowiada wyrażenie zawierające wywołanie metody withFilter. Następujące dwa wyrażenia są swoimi odpowiednikami.
scala> for (x <- Array(1,2,3) if x / 2 != 0) yield x*x res8: Array[Int] = Array(4, 9) scala> Array(1,2,3).withFilter(x => x / 2 != 0).map{ case x => x*x } res9: Array[Int] = Array(4, 9)
Specyfikacja języka Scala opisuje pętlę i wyrażenie for, w tym zasady przekształcania ich na wyrażenia zawierające metody map, withFilter, flatMap i foreach w punkcie 6.19. |