Kontynuuję kurs programowania w języku Scala, o którym wspominałam w poprzednim wpisie. Zgodnie z obietnicą, pokazuję kolejną fajną rzecz, której się nauczyłam.
Funkcje, które zwracają funkcje!
W Scali funkcje są tzw. obywatelami pierwszej kategorii (ang. first class citizens). Inaczej, funkcje są pierwszoklasowe. Oznacza to, iż można z nimi robić wszystko to, co można robić z “normalnymi” typami danych, to jest: przekazywać jako argumenty, przypisywać do zmiennych, zwracać z funkcji, tworzyć je na bieżąco.
W szczególności, jedna funkcja może zwrócić inną. Poniżej przykład.
type Set = Int => Boolean def singletonSet(elem: Int): Set = (elem2: Int) => { elem == elem2 }Na początku tworzymy alias o nazwie Set. Reprezentuje on typ funkcyjny: wszystkie funkcje pobierające parametr typu Int i zwracające wartość typu Boolean. W ten sposób chcemy, na potrzeby przykładu, reprezentować zbiory: jako funkcję, która dla każdej podanej liczby całkowitej powie nam, czy liczba ta należy do tego zbioru.
Jeśli nasz zbiór ma być zbiorem jednoelementowym (ang. singleton), to w zależności od tego, jaki to element, musielibyśmy utworzyć (nieskończenie) wiele funkcji sprawdzających, przynależność do zbioru – dla wszystkich możliwego elementu zbioru jednostkowego. Osobno dla zbioru zawierającego tylko liczbę 1, osobno dla liczby 2 itp. Dzięki możliwości zwracania funkcji, mamy tylko jedną funkcję, która tworzy i zwraca funkcję badającą przynależność do zbioru jednostkowego zawierającego wybrany element – przekazany jako parametr do funkcji singletonSet.
Jak to działa w praktyce?
test("singleton"){ val single = singletonSet(4) assert(single(4), "singleton contains") assert(!single(1), "singleton does not contain") }Na początku testu tworzymy zbiór jednoelementowy zawierający liczbę całkowitą 4. Nasz zbiór – czyli funkcję pobierającą argument Int, zwróconą z funkcji singletonSet – przypisujemy do zmiennej (hm, stałej adekwatnie) single.
Następnie, wywołując funkcję przypisaną do zmiennej single, sprawdzamy, czy do zbioru {4} należą odpowiednio liczby 4 oraz 1. Zgodnie z oczekiwaniami, dla 4 otrzymujemy wartość true, dla 1 wartość false.