Currying

Programowanie funkcyjne jest prawie tak samo popularne jak programowanie obiektowe. Wiele koncepcji z programowania obiektowego tak mocno przeniknęło do programowania w ogóle, że czasami nawet nie dostrzegamy pochodzenia danego podejścia. Programowanie funkcyjne również ma swoje ciekawe koncepcje - jedną z nich jest currying. W tym artykule staram się na przykładach pokazać jak działa currying oraz jakie problemy pozwala rozwiązać.

Matrioszki PAGES.POST.COVER_THUMBNAIL.BY_WHOM Frankenvrij

Z tego artykułu dowiesz się:

  • Co to jest currying?

  • Jak currying pomoże rozwiązać problem ze zbyt dużą liczbą argumentów w funkcji?

  • Gdzie możemy się spotkać z currying'iem w projektach z React?

  • Jak w Javascript działa konwertowanie do wartości prymitywnej?

Spotkaliście się kiedyś z problemem za dużej liczby argumentów w jednej funkcji? Takie funkcje stają się nieczytelne, a ich złożoność może prowadzić do trudności w samym procesie wytwarzania kodu i co za tym idzie - błędów. W wielu poradnikach i zestawieniach dobrych praktyk bardzo często wskazuje się, że funkcje nie powinny przyjmować więcej niż 1 lub 2 argumenty.

Dzisiaj chciałbym poruszyć ciekawy temat związany z programowaniem funkcyjnym, tj. currying. Na currying często mówi się, że jest to rozwijanie funkcji - wprowadza on możliwość elastycznego rozwijania funkcji przy zachowanie możliwie małej ilość przekazywanych argumentów.

Jedna funkcja, wiele argumentów

Najprostszym i najczęściej spotykanym przykładem, gdzie currying mógłby nam się przydać jest funkcja sumująca liczby.

Zwróćcie uwagę, że tak przygotowana funkcja jest mało elastyczna i zawsze musi przyjąć trzy argumenty. W przeciwnym wypadku zwróci nam błąd lub niepoprawny wynik.

Oczywiście możemy napisać tę funkcję w taki sposób, aby ilość argumentów nie miała znaczenia i funkcja nadal zwracała poprawny wynik, np:

Czy takie rozwiązanie jest w porządku? W pewnym sensie tak, ale duża ilość argumentów może w pewnym momencie spowodować, że nasz kod stanie się mało czytelny.

Jedna funkcja, jeden argument

Założenia currying’u są bardzo proste: funkcja przyjmuje minimalną ilość argumentów i jest na tyle elastyczna, że kolejne jej wywołania pozwolą nam otrzymać prawidłowy wynik. Wywołanie takie funkcji mogłoby wyglądać następująco:

W powyższym przykładzie mogę podawać kolejne argumenty do funkcji sum poprzez jej kolejne wywołania. Co się dzieje pod spodem? Funkcja sum zwraca funkcję pośrednią, która przyjmuje jeden argument i którą możemy wywołać ponownie. Zgodnie z definicją currying to przekształcenie jednej funkcji w sekwencję funkcji, do których przekazujemy po jednym argumencie. Napiszmy zatem funkcję sumującą, która przyjmie jeden argument i zwróci nową funkcję zwiększającą przekazaną liczbę przy kolejnym wywołaniu.

Powyższy przykład ilustruje zwrócenie przez naszą funkcję sum wewnętrznej funkcji add. Funkcja  sum przyjmuje jeden argument, podobnie zresztą jak funkcja wewnętrzna. Na każdym poziomie naszej funkcji zwracamy oczywiście funkcję wewnętrzną, bo to ona odpowiada za nasze obliczenia. Na tym etapie nasz kod jeszcze nie działa poprawnie. Wywołanie metody sum spowoduje, że zwrócimy funkcję, a nie jej wynik.

Aby zwrócić wartość z naszych obliczeń możemy dopisać wewnętrzną metodę getValue. Takie działanie będzie jak najbardziej poprawne, ponieważ w Javascript wszystko jest obiektem - funkcja również.

Jak widać na zaprezentowanym przykładzie osiągnęliśmy zamierzony efekt, ale pobranie wartości wymaga dodatkowego wywołania. Pojawia się zatem pytanie czy jesteśmy w stanie pominąć ostatni krok, tak aby ostatnie wywołanie od razu zwracało nam końcową wartość.

Konwertowanie do wartości prymitywnej

Javascript posiada wbudowaną metodę valueOf, która wywoływana jest automatycznie by przekonwertować obiekt do wartości prymitywnej. Warto zwrócić uwagę, że konwertowanie odbywa się przy użyciu innej wbudowanej metody toString. Mając tę wiedzę, możemy spokojnie założyć, że nadpisanie obu tych metod pozwoli nam zmienić wartość ostatecznie zwracaną. Jak mogłoby to wyglądać?

Metoda valueOf jest wywoływana przez interpreter Javascriptu, dlatego nie ma potrzeby, żebyśmy wywoływali ją samodzielnie. Pamiętajmy, że tak nadpisana funkcja nie powinna przyjmować argumentów.

Podsumowanie

Osiągnęliśmy nasz cel. Powyższe przykłady ilustrują jak można wykorzystać currying. Pytanie zatem czy warto? Wydaje mi się, że stosowanie tej techniki pozwala nam uelastycznić nasze funkcje i zwiększyć czytelność naszego kodu. Przykładów stosowania currying’u w codziennej pracy można znaleźć sporo - wystarczy zwrócić chociażby uwagę na React Redux. Metoda connect to dobry przykład zastosowania powyższych zasad:

Udostępnij ten artykuł:

Komentarze (0)

    Jeszcze nikt nic nie napisał, ale to znaczy że... możesz być pierwszy/pierwsza.

Powiązane treści

Jeżeli ten artykuł Cię zainteresował sprawdź inne materiały powiązane z nim tematycznie. Poniżej znajdziesz artykuły i odcinki podcastów mojego autorstwa oraz polecane przeze mnie książki, które rozszerzają ten temat.

Children by trilemedia
Artykuł
28 lipca 2022

Czy warto używać typu FC w React?

React daje nam różne możliwości dodawania specyficznych typów do różnych jego elementów. Możemy to osiągnąć na kilka sposobów. Dziś chciałbym się skupić na typowaniu statycznym i dynamicznym oraz typie FC, który spotkamy w React.

Czytaj więcej
React portals by Thomas Piekunka
Artykuł
14 października 2022

Poprzez portale w React

Podróże międzyplanetarne nie są jak narazie ani dostępne, ani popularne. Technicznie rzecz ujmując podobne trudności podróżowania pomiędzy różnymi sktrukturami DOM możemy spotkać w aplikacjach SPA. Dziś o rozwiązaniu tego problemu w React.

Czytaj więcej

Zapisz się do newslettera

Bądź na bieżąco z nowymi materiałami, ćwiczeniami i ciekawostkami ze świata IT. Dołącz do mnie.