11.2. Funkcje anonimowe

Definiując funkcje nie trzeba uciekać się do bezpośredniego rozszerzania jednej z klas o nazwie FunctionN i implementowania jej metody apply. Scala udostępnia specjalną notację pozwalającą definiować funkcje. Poniżej pokazano alternatywne sposoby zdefiniowania funkcji hello i isGreater z poprzedniego podrozdziału, przy czym są to definicje funkcji anonimowych, co oznacza, że tym funkcjom nie są nadawane nazwy.

Każda z powyższych definicji funkcji anonimowej składa się z deklaracji listy parametrów w nawiasach okrągłych, po której następuje podwójna strzałka w prawo (znaki => lub znak ), a po niej treść ciała funkcji. Choć tak zdefiniowana funkcja nie ma nazwy, to możemy ją przypisać do wartości zdefiniowanej za pomocą słowa kluczowego val i dalej odwoływać się do niej za pomocą nazwy tej wartości.

scala> val hello = () => "Hello!"
hello: () => String = <function0>

scala> val isGreater = (a: Int, b:Int) => a > b
isGreater: (Int, Int) => Boolean = <function2>

Tak zdefiniowane funkcje wywołujemy jak poprzednio.

scala> hello()
res0: String = Hello!

scala> isGreater(2,1)
res1: Boolean = true

Możemy również jawnie wywołać metodę apply.

scala> hello.apply()
res2: String = Hello!

scala> isGreater.apply(2,1)
res3: Boolean = true

Jeśli typ funkcji anonimowej jest znany — na przykład dzięki temu, że jawnie zadeklarujemy typ wartości do której przypisujemy funkcję — w definicji funkcji możemy zrezygnować z jawnego podawania typu parametrów.

scala> val isGreater: (Int, Int) => Boolean = (a,b) => a > b
isGreater: (Int, Int) => Boolean = <function2>

Możemy również zrobić to selektywnie.

scala> val isGreater: (Int, Int) => Boolean = (a:Int,b) => a > b
isGreater: (Int, Int) => Boolean = <function2>

scala> val isGreater: (Int, Int) => Boolean = (a,b:Int) => a > b
isGreater: (Int, Int) => Boolean = <function2>

W przypadku funkcji jednoparametrowej z pominiętą deklaracją typu możemy również pominąć nawiasy otaczające listę parametrów funkcji. Z taką sytuacją mamy do czynienia w następującej definicji.

scala> val isGreaterThan5: (Int) => Boolean = x => x > 5
isGreaterThan5: Int => Boolean = <function1>

Zapis definicji funkcji isGreater może być jeszcze krótszy. Zauważmy, że każdy z parametrów funkcji jest jest użyty w ciele funkcji tylko raz, a ponadto parametry są użyte w tej samej kolejności, w której występują na liście parametrów. W takiej sytuacji możemy pominąć deklaracje parametrów oraz podwójną strzałkę, a w ciele funkcji zastąpić odwołania do parametrów znakami podkreślenia. Definicja funkcji isGreater skraca się w ten sposób do następującej postaci.

scala> val isGreater: (Int, Int) => Boolean = _ > _
isGreater: (Int, Int) => Boolean = <function2>

Ponieważ definicja funkcji nie zawiera informacji o typach parametrów, próba zastosowania go z jednoczesnym pominięciem jawnej deklaracji typu funkcji — jak poniżej — kończy się komunikatem o błędzie.

scala> val isGreater = _ > _
<console>:10: error: missing parameter type for expanded function ((x$1, x$2) => x$1.$greater(x$2))
       val isGreater = _ > _
                       ^
<console>:10: error: missing parameter type for expanded function ((x$1: <error>, x$2) => x$1.$greater(x$2))
       val isGreater = _ > _
                           ^

Można jednak uzupełnić znaki podkreślenia oznaczające parametry funkcji deklaracjami typu.

scala> val isGreater = (_: Int) > (_: Int)
isGreater: (Int, Int) => Boolean = <function2>

Specyfikacja języka Scala opisuje funkcje anonimowe w punkcie 6.23. Scala umożliwia zastosowanie jeszcze innej specjalnej składni, która może być zastosowana do tworzenia funkcji anonimowych. Ta składnia zostanie przedstawiona w punkcie 14.15.

Język programowania Scala Wydanie 2. Copyright © Grzegorz Balcerek 2016

Licencja Creative Commons

Ten utwór jest dostępny na licencji Creative Commons Uznanie autorstwa-Na tych samych warunkach 4.0 Międzynarodowe.

Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.