From 34f058412919876e36fca0c7589d331987d10165 Mon Sep 17 00:00:00 2001 From: filemon Date: Sat, 8 Feb 2020 21:48:37 +0100 Subject: [PATCH 1/4] Polish version for-comprehensions --- _pl/tour/extractor-objects.md | 2 +- _pl/tour/for-comprehensions.md | 84 ++++++++++++++++++++++++++++++++++ _pl/tour/generic-classes.md | 2 +- 3 files changed, 86 insertions(+), 2 deletions(-) diff --git a/_pl/tour/extractor-objects.md b/_pl/tour/extractor-objects.md index 766c473d6e..12914321a1 100644 --- a/_pl/tour/extractor-objects.md +++ b/_pl/tour/extractor-objects.md @@ -5,7 +5,7 @@ partof: scala-tour num: 15 language: pl -next-page: generic-classes +next-page: for-comprehensions previous-page: regular-expression-patterns --- diff --git a/_pl/tour/for-comprehensions.md b/_pl/tour/for-comprehensions.md index 9d934c81fb..1b2168263b 100644 --- a/_pl/tour/for-comprehensions.md +++ b/_pl/tour/for-comprehensions.md @@ -2,5 +2,89 @@ layout: tour title: For Comprehensions partof: scala-tour + +num: 16 language: pl +next-page: generic-classes +previous-page: extractor-objects --- + +Trudno znaleźć dobre tłumaczenie _for comprehensions_ w języku polskim, dlatego stosujemy wersję angielską. + +Scala oferuje prostą w zapisie formę wyrażania _sequence comprehensions._ +_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. + +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. + +```tut +case class Osoba(imie: String, wiek: Int) + +val spisOsob = List( + Osoba("Monika", 25), + Osoba("Czarek", 35), + Osoba("Marcin", 26), + Osoba("Filip", 25) +) + +val imiona = for ( + osoba <- spisOsob if (osoba.wiek >=30 && osoba.wiek < 40) +) yield osoba.imie // czyli dodaj do listy wynikowej + +imiona.foreach(imie => println(imie)) // wydrukowane zostanie: Czarek +``` + +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]`. + +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. + +```tut +def pary(n: Int) = + for ( + i <- 0 until n; + j <- 0 until n if i == j + ) yield (i, j) + +pary(10, 10) foreach { + case (i, j) => + 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) +} +``` + +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: + +``` +(0, 0) (0, 1) (0, 2) (0, 3) (0, 4) (0, 5) (0, 6) (0, 7) (0, 8) (0, 9) (1, 0) ... +``` + +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_. + +Przykładem innego użycia _comprehensions_ jest jego wykorzystanie do obsługi typu `Option`. +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`. + +Spójrzmy poniżej: + +```tut +case class Student(imie: String, nazwisko: String) + +val imieOpt: Option[String] = Some("Jerzy") +val nazwiskoOpt: Option[String] = Some("Jurkowski") + +val student = for { + imie <- imieOpt + nazwisko <- nazwiskoOpt + } yield Student(imie, nazwisko) // wynik będzie typu Option[Student]. +``` + +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]`. + +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`. + + +```tut +def licz(n: Int) = + for (i <- 0 until n) + println(s"$i ") + +licz(10) +``` + diff --git a/_pl/tour/generic-classes.md b/_pl/tour/generic-classes.md index 257b8b0592..c64a839b39 100644 --- a/_pl/tour/generic-classes.md +++ b/_pl/tour/generic-classes.md @@ -6,7 +6,7 @@ partof: scala-tour num: 17 language: pl next-page: variances -previous-page: extractor-objects +previous-page: for-comprehensions --- Scala posiada wbudowaną obsługą klas parametryzowanych przez typy. Tego typu klasy generyczne są szczególnie użyteczne podczas tworzenia klas kolekcji. From faaf68be8b9015aae742750a542a60378a373edc Mon Sep 17 00:00:00 2001 From: filemon Date: Thu, 13 Feb 2020 19:15:56 +0100 Subject: [PATCH 2/4] English examples --- _pl/tour/for-comprehensions.md | 48 +++++++++++++++++----------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/_pl/tour/for-comprehensions.md b/_pl/tour/for-comprehensions.md index 1b2168263b..4c94f3fe00 100644 --- a/_pl/tour/for-comprehensions.md +++ b/_pl/tour/for-comprehensions.md @@ -12,39 +12,39 @@ previous-page: extractor-objects Trudno znaleźć dobre tłumaczenie _for comprehensions_ w języku polskim, dlatego stosujemy wersję angielską. Scala oferuje prostą w zapisie formę wyrażania _sequence comprehensions._ -_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. +_For comprehensions_ przedstawione jest w formie `for (enumerators) yield e`, gdzie `enumerators` 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. 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. ```tut -case class Osoba(imie: String, wiek: Int) +case class Person(name: String, age: Int) -val spisOsob = List( - Osoba("Monika", 25), - Osoba("Czarek", 35), - Osoba("Marcin", 26), - Osoba("Filip", 25) +val people = List( + Person("Monika", 25), + Person("Czarek", 35), + Person("Marcin", 26), + Person("Filip", 25) ) -val imiona = for ( - osoba <- spisOsob if (osoba.wiek >=30 && osoba.wiek < 40) -) yield osoba.imie // czyli dodaj do listy wynikowej +val names = for ( + person <- people if (person.age >=30 && person.age < 40) +) yield person.name // czyli dodaj do listy wynikowej -imiona.foreach(imie => println(imie)) // wydrukowane zostanie: Czarek +names.foreach(name => println(name)) // wydrukowane zostanie: Czarek ``` -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]`. +Na początku `for` znajduje się generator `person <- people`. Następujące po tym wyrażenie warunkowe `if (person.age >=30 && person.age < 40)` odfiltrowuje wszystkie osoby poniżej 30 i powyżej 40 roku życia. W powyższym przykładzie po wyrażeniu `yield` wywołano `person.name`, `name` jest typu `String`, więc lista wynikowa będzie typu `List[String]`. W ten sposób lista typu `List[Person]` została przekształcona na listę `Lista[String]`. 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. ```tut -def pary(n: Int) = +def someTuple(n: Int) = for ( i <- 0 until n; j <- 0 until n if i == j ) yield (i, j) -pary(10, 10) foreach { +someTuple(10, 10) foreach { case (i, j) => 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) } @@ -64,27 +64,27 @@ Załóżmy, że mamy dwie wartości `Option[String]` i chcielibyśmy zwrócić o Spójrzmy poniżej: ```tut -case class Student(imie: String, nazwisko: String) +case class Student(name: String, surname: String) -val imieOpt: Option[String] = Some("Jerzy") -val nazwiskoOpt: Option[String] = Some("Jurkowski") +val nameOpt: Option[String] = Some("John") +val surnameOpt: Option[String] = Some("Casey") val student = for { - imie <- imieOpt - nazwisko <- nazwiskoOpt - } yield Student(imie, nazwisko) // wynik będzie typu Option[Student]. + name <- nameOpt + surname <- surnameOpt + } yield Student(name, surname) // wynik będzie typu Option[Student]. ``` -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]`. +Jeżeli `name` lub `surname` 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]`. -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`. +Wszystkie powyższe przykłady posiadały wyrażenie `yield` na końcu _comprehensions_, jednak nie jest to obligatoryjne. Gdy `yield` nie zostanie 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`. ```tut -def licz(n: Int) = +def count(n: Int) = for (i <- 0 until n) println(s"$i ") -licz(10) +count(10) // wyświetli "0 1 2 3 4 5 6 7 8 9 " ``` From 6d5d4460ba18c953ed51c6c926f96f4f400a7ee3 Mon Sep 17 00:00:00 2001 From: filemon Date: Thu, 13 Feb 2020 19:15:56 +0100 Subject: [PATCH 3/4] English examples --- _pl/tour/for-comprehensions.md | 52 +++++++++++++++++----------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/_pl/tour/for-comprehensions.md b/_pl/tour/for-comprehensions.md index 1b2168263b..909e90918d 100644 --- a/_pl/tour/for-comprehensions.md +++ b/_pl/tour/for-comprehensions.md @@ -12,39 +12,39 @@ previous-page: extractor-objects Trudno znaleźć dobre tłumaczenie _for comprehensions_ w języku polskim, dlatego stosujemy wersję angielską. Scala oferuje prostą w zapisie formę wyrażania _sequence comprehensions._ -_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. +_For comprehensions_ przedstawione jest w formie `for (enumerators) yield e`, gdzie `enumerators` 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. 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. ```tut -case class Osoba(imie: String, wiek: Int) +case class Person(name: String, age: Int) -val spisOsob = List( - Osoba("Monika", 25), - Osoba("Czarek", 35), - Osoba("Marcin", 26), - Osoba("Filip", 25) +val people = List( + Person("Monika", 25), + Person("Czarek", 35), + Person("Marcin", 26), + Person("Filip", 25) ) -val imiona = for ( - osoba <- spisOsob if (osoba.wiek >=30 && osoba.wiek < 40) -) yield osoba.imie // czyli dodaj do listy wynikowej +val names = for ( + person <- people if (person.age >=30 && person.age < 40) +) yield person.name // czyli dodaj do listy wynikowej -imiona.foreach(imie => println(imie)) // wydrukowane zostanie: Czarek +names.foreach(name => println(name)) // wydrukowane zostanie: Czarek ``` -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]`. +Na początku `for` znajduje się generator `person <- people`. Następujące po tym wyrażenie warunkowe `if (person.age >=30 && person.age < 40)` odfiltrowuje wszystkie osoby poniżej 30 i powyżej 40 roku życia. W powyższym przykładzie po wyrażeniu `yield` wywołano `person.name`, `name` jest typu `String`, więc lista wynikowa będzie typu `List[String]`. W ten sposób lista typu `List[Person]` została przekształcona na listę `Lista[String]`. 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. ```tut -def pary(n: Int) = +def someTuple(n: Int) = for ( i <- 0 until n; j <- 0 until n if i == j ) yield (i, j) -pary(10, 10) foreach { +someTuple(10) foreach { case (i, j) => 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) } @@ -64,27 +64,27 @@ Załóżmy, że mamy dwie wartości `Option[String]` i chcielibyśmy zwrócić o Spójrzmy poniżej: ```tut -case class Student(imie: String, nazwisko: String) +case class Student(name: String, surname: String) -val imieOpt: Option[String] = Some("Jerzy") -val nazwiskoOpt: Option[String] = Some("Jurkowski") +val nameOpt: Option[String] = Some("John") +val surnameOpt: Option[String] = Some("Casey") val student = for { - imie <- imieOpt - nazwisko <- nazwiskoOpt - } yield Student(imie, nazwisko) // wynik będzie typu Option[Student]. + name <- nameOpt + surname <- surnameOpt + } yield Student(name, surname) // wynik będzie typu Option[Student]. ``` -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]`. +Jeżeli `name` lub `surname` 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]`. -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`. +Wszystkie powyższe przykłady posiadały wyrażenie `yield` na końcu _comprehensions_, jednak nie jest to obligatoryjne. Gdy `yield` nie zostanie 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`. ```tut -def licz(n: Int) = - for (i <- 0 until n) - println(s"$i ") +def count(n: Int) = + for (i <- 0 until n) + println(s"$i ") -licz(10) +count(10) // wyświetli "0 1 2 3 4 5 6 7 8 9 " ``` From 0b6f5fcb6ec5b32dafbf158c4818b747e795b205 Mon Sep 17 00:00:00 2001 From: filemon Date: Thu, 13 Feb 2020 21:28:54 +0100 Subject: [PATCH 4/4] tut corrections --- _pl/tour/for-comprehensions.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/_pl/tour/for-comprehensions.md b/_pl/tour/for-comprehensions.md index 3b1ecca864..909e90918d 100644 --- a/_pl/tour/for-comprehensions.md +++ b/_pl/tour/for-comprehensions.md @@ -44,11 +44,7 @@ def someTuple(n: Int) = j <- 0 until n if i == j ) yield (i, j) -<<<<<<< HEAD someTuple(10) foreach { -======= -someTuple(10, 10) foreach { ->>>>>>> faaf68be8b9015aae742750a542a60378a373edc case (i, j) => 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) } @@ -86,13 +82,8 @@ Wszystkie powyższe przykłady posiadały wyrażenie `yield` na końcu _comprehe ```tut def count(n: Int) = -<<<<<<< HEAD for (i <- 0 until n) println(s"$i ") -======= - for (i <- 0 until n) - println(s"$i ") ->>>>>>> faaf68be8b9015aae742750a542a60378a373edc count(10) // wyświetli "0 1 2 3 4 5 6 7 8 9 " ```