Scala Language
Funkcje
Szukaj…
Uwagi
Scala ma pierwszorzędne funkcje.
Różnica między funkcjami i metodami:
Funkcja nie jest metodą w Scali: funkcje są wartością i mogą być przypisane jako takie. Z drugiej strony metody (utworzone za pomocą def
) muszą należeć do klasy, cechy lub obiektu.
- Funkcje są kompilowane do klasy rozszerzającej cechę (taką jak
Function1
) w czasie kompilacji i są tworzone w instancji do wartości w czasie wykonywania. Z drugiej strony metody są członkami ich klasy, cechy lub przedmiotu i nie istnieją poza tym. - Metodę można przekonwertować na funkcję, ale funkcji nie można przekonwertować na metodę.
- Metody mogą mieć parametryzację typu, podczas gdy funkcje nie.
- Metody mogą mieć domyślne wartości parametrów, podczas gdy funkcje nie.
Funkcje anonimowe
Funkcje anonimowe to funkcje, które są zdefiniowane, ale nie mają przypisanej nazwy.
Poniżej znajduje się anonimowa funkcja, która przyjmuje dwie liczby całkowite i zwraca sumę.
(x: Int, y: Int) => x + y
Wynikowe wyrażenie można przypisać do val
:
val sum = (x: Int, y: Int) => x + y
Funkcje anonimowe są przede wszystkim używane jako argumenty innych funkcji. Na przykład funkcja map
w kolekcji oczekuje innej funkcji jako argumentu:
// Returns Seq("FOO", "BAR", "QUX")
Seq("Foo", "Bar", "Qux").map((x: String) => x.toUpperCase)
Typy argumentów funkcji anonimowej można pominąć: typy są wywnioskowane automatycznie :
Seq("Foo", "Bar", "Qux").map((x) => x.toUpperCase)
Jeśli jest tylko jeden argument, nawiasy wokół tego argumentu można pominąć:
Seq("Foo", "Bar", "Qux").map(x => x.toUpperCase)
Podkreśla skrót
Istnieje jeszcze krótsza składnia, która nie wymaga nazw argumentów. Powyższy fragment kodu można zapisać:
Seq("Foo", "Bar", "Qux").map(_.toUpperCase)
_
reprezentuje argumenty funkcji anonimowej w położeniu. W przypadku anonimowej funkcji, która ma wiele parametrów, każde wystąpienie _
będzie odnosić się do innego argumentu. Na przykład dwa następujące wyrażenia są równoważne:
// Returns "FooBarQux" in both cases
Seq("Foo", "Bar", "Qux").reduce((s1, s2) => s1 + s2)
Seq("Foo", "Bar", "Qux").reduce(_ + _)
Podczas używania tego skrótu do dowolnego argumentu reprezentowanego przez pozycję _
można odwoływać się tylko raz i w tej samej kolejności.
Anonimowe funkcje bez parametrów
Aby utworzyć wartość dla funkcji anonimowej, która nie przyjmuje parametrów, pozostaw listę parametrów pustą:
val sayHello = () => println("hello")
Kompozycja
Kompozycja funkcji pozwala na działanie dwóch funkcji i może być postrzegana jako jedna funkcja. Wyrażony w kategoriach matematycznych, biorąc pod uwagę funkcję f(x)
i funkcję g(x)
, funkcja h(x) = f(g(x))
.
Gdy funkcja jest kompilowana, jest ona kompilowana do typu związanego z Function1
. Scala udostępnia dwie metody implementacji Function1
związane ze składem: oraz andThen
i compose
. Metoda compose
pasuje do powyższej definicji matematycznej:
val f: B => C = ...
val g: A => B = ...
val h: A => C = f compose g
The andThen
(think h(x) = g(f(x))
) ma wrażenie bardziej „DSL”:
val f: A => B = ...
val g: B => C = ...
val h: A => C = f andThen g
Nowa anonimowa funkcja jest przypisana, która jest zamknięta nad f
i g
. W obu przypadkach ta funkcja jest powiązana z nową funkcją h
.
def andThen(g: B => C): A => C = new (A => C){
def apply(x: A) = g(self(x))
}
Jeśli albo f
lub g
działa poprzez efekt uboczny, wówczas wywołanie h
spowoduje, że wszystkie skutki uboczne f
i g
wystąpią w kolejności. To samo dotyczy wszelkich zmian stanu zmiennego.
Związek z funkcjami częściowymi
trait PartialFunction[-A, +B] extends (A => B)
Każdy pojedynczy argument PartialFunction
jest także Function1
. Jest to sprzeczne z intuicją w formalnym sensie matematycznym, ale lepiej pasuje do projektowania obiektowego. Z tego powodu Function1
nie musi zapewniać stałej true
metody isDefinedAt
.
Aby zdefiniować funkcję częściową (która jest również funkcją), użyj następującej składni:
{ case i: Int => i + 1 } // or equivalently { case i: Int ⇒ i + 1 }
Aby uzyskać więcej informacji, zobacz PartialFunctions .