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.
Dla przykładu przyjrzyjmy się metodzie foldLeft
zdefiniowanej w Traversable 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.
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
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
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})
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.
numbers.foldLeft(0)(_ + _)
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:
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)
Podsumowując, foldLeft
oraz foldRight
mogą być używane w dowolnej z poniższych postaci:
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)
Contributors to this page:
Contents
- Wprowadzenie
- Podstawy
- Hierarchia typów
- Klasy
- Domyślne wartości parametrów
- Parametry nazwane
- Cechy
- Krotki
- Kompozycja klas przez domieszki
- Funkcje wyższego rzędu
- Funkcje zagnieżdżone
- Rozwijanie funkcji (Currying)
- Klasy przypadków
- Dopasowanie wzorców (Pattern matching)
- Obiekty singleton
- Wzorce wyrażeń regularnych
- Obiekty ekstraktorów
- For Comprehensions
- Klasy generyczne
- Wariancje
- Górne ograniczenia typów
- Dolne ograniczenia typów
- Klasy wewnętrzne
- Typy abstrakcyjne
- Typy złożone
- Jawnie typowane samoreferencje
- Parametry domniemane
- Konwersje niejawne
- Metody polimorficzne
- Lokalna inferencja typów
- Operatory
- Parametry przekazywane według nazwy
- Adnotacje
- Pakiety i importy
- Obiekty pakietu