This page is available only in polish

I am working on the translation!

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

From this article you will learn:

  • 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:

Share this article:

Comments (0)

    No one has posted anything yet, but that means.... you may be the first.

You may be interested in

lorem

Botox Injections by Jacob Lund
Article
24 February 2022

Dependency Injection

W trakcie nauki programowania prędzej czy później spotkamy się z wzorcami projektowymi. Gdy już je poznamy okazuje się, że są wszędzie i stosujemy je nawet nie mając świadomości, że to robimy. Dziś o jednym z wzorców projektowych - Dependency Injection.

Read more
React portals by Thomas Piekunka
Article
14 October 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.

Read more
Road to the Horizon by Larisa K
Article
29 July 2019

Context API w React

Każda kolejna wersja Reacta dostarcza nam coraz lepszych i ciekawszych narzędzi, które mają poprawić jakość naszej pracy z kodem, który tworzymy. Nie inaczej jest z Context API, które pojawiło się w React w wersji 16.3.

Read more

Zapisz się do newslettera

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