Skip to content

Commit 34f0584

Browse files
committed
Polish version for-comprehensions
1 parent 4781130 commit 34f0584

File tree

3 files changed

+86
-2
lines changed

3 files changed

+86
-2
lines changed

_pl/tour/extractor-objects.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ partof: scala-tour
55

66
num: 15
77
language: pl
8-
next-page: generic-classes
8+
next-page: for-comprehensions
99
previous-page: regular-expression-patterns
1010
---
1111

_pl/tour/for-comprehensions.md

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,89 @@
22
layout: tour
33
title: For Comprehensions
44
partof: scala-tour
5+
6+
num: 16
57
language: pl
8+
next-page: generic-classes
9+
previous-page: extractor-objects
610
---
11+
12+
Trudno znaleźć dobre tłumaczenie _for comprehensions_ w języku polskim, dlatego stosujemy wersję angielską.
13+
14+
Scala oferuje prostą w zapisie formę wyrażania _sequence comprehensions._
15+
_For comprehensions_ przedstawione jest w formie `for (enumeratory) yield e`, gdzie `enumeratory` to lista enumeratorów oddzielonych średnikami. _Enumerator_ może być zarówno generatorem nowych wartości lub filtrem dla wartości przetwarzanych. Wyrażenie to definiuje ciało `e` dla każdej wartości wywołanej przez enumerator i zwraca te wartości w postaci sekwencji.
16+
17+
Poniżej znajduje się przykład, który przekształca listę osób na listę imion osób, których wiek mieści się w przedziale od 30 do 40 lat.
18+
19+
```tut
20+
case class Osoba(imie: String, wiek: Int)
21+
22+
val spisOsob = List(
23+
Osoba("Monika", 25),
24+
Osoba("Czarek", 35),
25+
Osoba("Marcin", 26),
26+
Osoba("Filip", 25)
27+
)
28+
29+
val imiona = for (
30+
osoba <- spisOsob if (osoba.wiek >=30 && osoba.wiek < 40)
31+
) yield osoba.imie // czyli dodaj do listy wynikowej
32+
33+
imiona.foreach(imie => println(imie)) // wydrukowane zostanie: Czarek
34+
```
35+
36+
Na początku `for` znajduje się generator `osoba <- spisOsob`. Następujące po tym wyrażenie warunkowe `if (osoba.wiek >=30 && osoba.wiek < 40)` odfiltrowuje wszystkie osoby poniżej 30 i powyżej 40 roku życia. W powyższym przykładzie po wyrażeniu `yield` wywołano `osoba.imie`, `imie` jest typu `String`, więc lista wynikowa będzie typu `List[String]`. W ten sposób lista typu `List[Osoba]` została przekształcona na listę `Lista[String]`.
37+
38+
Poniżej znajduje się bardziej złożony przykład, który używa dwóch generatorów. Jego zadaniem jest sprawdzenie wszystkich par liczb od `0` do `n-1` i wybór tylko tych par, których wartości są sobie równe.
39+
40+
```tut
41+
def pary(n: Int) =
42+
for (
43+
i <- 0 until n;
44+
j <- 0 until n if i == j
45+
) yield (i, j)
46+
47+
pary(10, 10) foreach {
48+
case (i, j) =>
49+
println(s"($i, $j) ") // drukuje (0, 0) (1, 1) (2, 2) (3, 3) (4, 4) (5, 5) (6, 6) (7, 7) (8, 8) (9, 9)
50+
}
51+
```
52+
53+
Załóżmy, że wartością początkową jest `n == 10`. W pierwszej iteracji `i` przyjmuje wartość równą `0` tak samo jak `j`, filtr `i == j` zwróci `true` więc zostanie przekazane do `yield`. W kolejnej iteracji `j` przyjmie wartość równą `1`, więc `i == j` zwróci `false`, ponieważ `0 != 1` i nie zostanie przekazane do `yield`. Kolejne osiem iteracji to zwiększanie wartości `j` aż osiągnie wartość równą `9`. W następnej iteracji `j` powraca do wartości `0`, a `i` zostaje zwiększona o `1`. Gdyby w powyższym przykładzie nie umieszczono filtra `i == j` wydrukowana zostałaby prosta sekwencja:
54+
55+
```
56+
(0, 0) (0, 1) (0, 2) (0, 3) (0, 4) (0, 5) (0, 6) (0, 7) (0, 8) (0, 9) (1, 0) ...
57+
```
58+
59+
Bardzo istotne jest to, że comprehensions nie są ograniczone do list. Każdy typ danych, który wspiera operację `withFilter`, `map` czy `flatMap` (z odpowiednim typem) może być użyty w _sequence comprehensions_.
60+
61+
Przykładem innego użycia _comprehensions_ jest jego wykorzystanie do obsługi typu `Option`.
62+
Załóżmy, że mamy dwie wartości `Option[String]` i chcielibyśmy zwrócić obiekt `Student(imie: String, nazwisko: String` tylko gdy obie wartości są zadeklarowane - nie są `None`.
63+
64+
Spójrzmy poniżej:
65+
66+
```tut
67+
case class Student(imie: String, nazwisko: String)
68+
69+
val imieOpt: Option[String] = Some("Jerzy")
70+
val nazwiskoOpt: Option[String] = Some("Jurkowski")
71+
72+
val student = for {
73+
imie <- imieOpt
74+
nazwisko <- nazwiskoOpt
75+
} yield Student(imie, nazwisko) // wynik będzie typu Option[Student].
76+
```
77+
78+
Jeżeli `imie` lub `nazwisko` nie byłyby określone, np. przyjmowałyby wartość równą `None` to zmienna `student` również byłaby `None`. Powyższy przykład to przekształcenie dwóch wartości `Option[String]` na `Option[Student]`.
79+
80+
Wszystkie powyższe przykłady posiadały wyrażenie `yield` na końcu _comprehensions_, jednak nie jest to obligatoryjne. Gdy `yield` nie zostane dodanie zwrócony zostanie `Unit`. Takie rozwiązanie może być przydatne gdy chcemy uzyskać jakieś skutki uboczne. Poniższy przykład wypisuje liczby od 0 do 9 bez użycia `yield`.
81+
82+
83+
```tut
84+
def licz(n: Int) =
85+
for (i <- 0 until n)
86+
println(s"$i ")
87+
88+
licz(10)
89+
```
90+

_pl/tour/generic-classes.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ partof: scala-tour
66
num: 17
77
language: pl
88
next-page: variances
9-
previous-page: extractor-objects
9+
previous-page: for-comprehensions
1010
---
1111

1212
Scala posiada wbudowaną obsługą klas parametryzowanych przez typy. Tego typu klasy generyczne są szczególnie użyteczne podczas tworzenia klas kolekcji.

0 commit comments

Comments
 (0)