Podstawy Programowania Funkcyjnego #5 Partial Aplication, Currying


W tej serii uczymy się Podstaw Programowania Funkcyjnego. Wykorzystamy przy okazji wiedzę zdobytą w serii dotyczącej ES6. Tym razem dowiemy się czym są oraz czym się różnią terminy Partial Application oraz Currying. Zaczynajmy!
# Partial Application
Standardowo dla stworzonej wcześniej funkcji, przy wywołaniu "aplikujemy" jednocześnie wszystkie argumenty i oczekujemy na jej rezultat. Wyobraźmy sobie panel sterowania statku kosmicznego, w którym musimy podawać komunikaty o kolorze świecącej się diody:
Jeżeli świeci się czerwona dioda, wyświetlimy komunikat checkLed("dioda","czerwony");
, jednak kod traci na czytelności i za każdym razem musimy używać słowa "dioda".
Żeby wyeliminować ciągłe powtarzanie tego elementu zastosujemy częściową aplikację argumentów (Partial Application), równocześnie zachowując możliwość zmiany słowa "dioda" w przyszłości.
Jeśli nie korzystamy z funkcji strzałkowych, to możemy skorzystać z funkcji bind, lub stworzyć Higher Order Function:
# Currying
Na jednej z rozmów kwalifikacyjnych padło pytanie, czy funkcja(a)(b)
jest poprawnym kodem w języku JavaScript. To dziwne wywołanie kodu to Currying. Currying jest terminem, którego nie da się przetłumaczyć, ponieważ pochodzi od nazwiska matematyka - Haskell Brooks Curry. Na jego cześć został nazwany język programowania "Haskell".
A więc czym jest currying? To przetwarzanie funkcji o wielu argumentach we funkcje jednoargumentowe. Dzięki temu otrzymujemy funkcję, która przyjmuje po jednym argumencie na każdym etapie wywołania.
Co to w praktyce oznacza? Funkcja po przyjęciu pierwszego argumentu zwraca kolejną funkcję przyjmującą kolejny, pojedynczy argument. Na początek zróbmy zwykłą funkcję przyjmującą trzy argumenty:
A teraz dla porównania stwórzmy przy użyciu ES6 funkcję przyjmującą po jednym argumencie:
Funkcyjne języki programowania posiadają funkcje, które pozwalają na Currying zwykych funkcji. Niestety w JavaScript nie mamy takiej funkcji wbudowanej, dlatego musimy skorzystać z biblioteki Lodash:
Używamy zwykłej funkcji checkIndicator
, którą stworzyliśmy wcześniej i używamy funkcji Lodash _.curry()
. Teraz możemy aplikować po jednym argumencie.
# Currying - zastosowania
Dlaczego powinno się stosować currying, skoro na pierwszy rzut oka nie ma to żadnych korzyści?
W miarę poznawania kolejnych zagadnień programowania funkcyjnego currying będzie coraz bardziej potrzebny. Ułatwi nam pracę z map oraz kompozycją funkcji, którą poznamy wkrótce na blogu. Poza tym, currying daje nam dużą elastyczność, pozwala na reusability poprzednich funkcji, oraz pozwala stosować partial application bez modyfikacji pierwotnej funkcji:
Po użyciu funkcji _.curry()
podajemy pierwszy argument "czerwona"
a dopiero później podajemy resztę argumentów. Nasza pierwotna funkcja checkIndicator
nie musi zwracać kolejnej funkcji żeby zrobić partial application
. Dzięki temu zabiegowi początkowa funkcja nie musi być w ogóle modyfikowana, a cel jakim była częściowa aplikacja argumentów został zrealizowany.