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.

Published: October 22 2017

blog comments powered by Disqus