diff --git a/_pl/tour/multiple-parameter-lists.md b/_pl/tour/multiple-parameter-lists.md index 29735548cc..ec2d8e378b 100644 --- a/_pl/tour/multiple-parameter-lists.md +++ b/_pl/tour/multiple-parameter-lists.md @@ -6,37 +6,77 @@ discourse: false partof: scala-tour -num: 9 +num: 10 language: pl next-page: case-classes previous-page: nested-functions --- -Funkcja może określić dowolną ilość list parametrów. Kiedy jest ona wywołana dla mniejszej liczby niż zostało to zdefiniowane, zwraca funkcję pobierającą dalsze listy parametrów jako jej argument. +Metoda może określać dowolną liczbę list parametrów. +W sytuacji, kiedy jest ona wywołana dla mniejszej liczby list parametrów niż zostało to zdefiniowane, zwracana jest funkcja oczekująca pozostałych list parametrów jako argumentów. -Przykład rozwijania funkcji: +Dla przykładu przyjrzyjmy się metodzie `foldLeft` zdefiniowanej w [Traversable](/overviews/collections/trait-traversable.html) z kolekcji w Scali: +``` +def foldLeft[B](z: B)(op: (B, A) => B): B +``` + +Metoda `foldLeft` stosuje binarny operator `op` na wartości początkowej `z` oraz wszystkich elementach zawartych w aktualnym obiekcie `Traversable` - idąc od lewej do prawej strony. +Poniżej omówiony jest przykład użycia. + +Zaczynając od początkowej wartości 0, funkcja `foldLeft` stosuje funkcję `(m, n) => m + n` na każdym elemencie listy oraz poprzedniej zakumulowanej wartości. + +{% scalafiddle %} ```tut -object CurryTest extends App { +val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) +val res = numbers.foldLeft(0)((m, n) => m + n) +println(res) // 55 +``` +{% endscalafiddle %} + +Metody z wieloma listami parametrów mają bardziej dosadną składnię wywoływania, dlatego powinny być używane oszczędnie. +Sugerowane przypadki użycia obejmują: + +#### Funkcja jako pojedynczy parametr - def filter(xs: List[Int], p: Int => Boolean): List[Int] = - if (xs.isEmpty) xs - else if (p(xs.head)) xs.head :: filter(xs.tail, p) - else filter(xs.tail, p) +W przypadku funkcji jako pojedynczego parametru, tak jak w przypadku `op` z `foldLeft` powyżej, wiele list parametrów pozwala na bardziej zwięzłą składnię przy przekazywaniu funkcji anonimowej do metody. +Bez wielu list parametrów kod wyglądałby w następujący sposób: + +``` +numbers.foldLeft(0, {(m: Int, n: Int) => m + n}) +``` - def modN(n: Int)(x: Int) = ((x % n) == 0) +Zauważ, że użycie wielu list parametrów pozwala na wykorzystanie wnioskowania typów, co z kolei czyni kod bardziej zwięzłym (jak pokazano poniżej). +Używając standardowej definicji metody, nie byłoby to możliwe. - val nums = List(1, 2, 3, 4, 5, 6, 7, 8) - println(filter(nums, modN(2))) - println(filter(nums, modN(3))) -} +``` +numbers.foldLeft(0)(_ + _) ``` -_Uwaga: metoda `modN` jest częściowo zastosowana dla dwóch wywołań `filter`, gdyż jest wywołana tylko dla jej pierwszego argumentu. Wyrażenie `modN(2)` zwraca funkcję typu `Int => Boolean` - stąd też może być przekazane jako drugi argument funkcji `filter`._ +Powyższe wyrażenie `numbers.foldLeft(0)(_ + _)` pozwala trwale ustawić parametr `z` i przekazywać dalej częściową funkcję (partial function), tak jak pokazano to poniżej: -Wynik działania powyższego programu: +```tut +val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) +val numberFunc = numbers.foldLeft(List[Int]())_ +val squares = numberFunc((xs, x) => xs:+ x*x) +print(squares.toString()) // List(1, 4, 9, 16, 25, 36, 49, 64, 81, 100) + +val cubes = numberFunc((xs, x) => xs:+ x*x*x) +print(cubes.toString()) // List(1, 8, 27, 64, 125, 216, 343, 512, 729, 1000) ``` -List(2,4,6,8) -List(3,6) + +Podsumowując, `foldLeft` oraz `foldRight` mogą być używane w dowolnej z poniższych postaci: + +```tut +val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + +numbers.foldLeft(0)((sum, item) => sum + item) // postać ogólna +numbers.foldRight(0)((sum, item) => sum + item) // postać ogólna + +numbers.foldLeft(0)(_+_) // postać rozwijana (curried) +numbers.foldRight(0)(_+_) // postać rozwijana (curried) + +(0 /: numbers)(_+_) // Alternatywy sposób wywołania foldLeft +(numbers :\ 0)(_+_) // Alternatywy sposób wywołania foldRight ``` diff --git a/_tour/multiple-parameter-lists.md b/_tour/multiple-parameter-lists.md index 7d4ae731e1..8dae99e656 100644 --- a/_tour/multiple-parameter-lists.md +++ b/_tour/multiple-parameter-lists.md @@ -25,11 +25,13 @@ def foldLeft[B](z: B)(op: (B, A) => B): B Starting with an initial value of 0, `foldLeft` here applies the function `(m, n) => m + n` to each element in the List and the previous accumulated value. +{% scalafiddle %} ```tut val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) val res = numbers.foldLeft(0)((m, n) => m + n) -print(res) // 55 +println(res) // 55 ``` +{% endscalafiddle %} Multiple parameter lists have a more verbose invocation syntax; and hence should be used sparingly. Suggested use cases include: