Podstawy Programowania Funkcyjnego #1 - fundamenty


W tej serii możecie nauczyć się razem ze mną Podstaw Programowania Funkcyjnego. Będzie to świetny sposób na poznanie zastosowań standardu JavaScript - ES6. Nawet jeśli piszesz kod obiektowo, warto poznać kilka podstaw, które pozwolą pisać krótszy i czytelniejszy kod. Na sam początek zaczniemy od fundamentów i poznamy najważniejsze zasady. Zaczynajmy!
# Argumenty funkcji
W języku JavaScript, funkcja może przyjmować różną ilość argumentów i zależnie od ich ilości możemy wykonać w niej inny fragment kodu. Wcześniej, czyli przed wprowadzeniem standardu ES6 mogliśmy korzystać tylko ze specjalnej zmiennej arguments
, jednak mamy teraz lepsze możliwości, a korzystanie z tej zmiennej uznawane jest za złą praktykę.
Spójrzmy na poniższy kod, który korzysta z tej zmiennej:
var show = function(a, b) {
console.log(arguments);
}
show('pierwszy', 'drugi'); //{ '0': 'pierwszy', '1': 'drugi' }
Zakładając że nie znamy ilości argumentów, które pojawią się w tej funkcji, możemy wywołać funkcję length
do zmiennej arguments
:
var show = function() {
console.log(arguments.length);
}
show('a','b','c','d'); //4
Skoro zmienna arguments
działa całkowicie w porządku, to można zadać pytanie, dlaczego nie powinno się jej stosować?
arguments.length
jest bardzo użytecznym zastosowaniem, jednak problem zaczyna się w momencie, gdy chcielibyśmy użyć argumentów z tej zmiennej, bo nie jest ona prawdziwą tablicą.
Jak więc zastąpić arguments
? Na ratunek przychodzi zmienna rest
, którą omówiliśmy już przy okazji postu dotyczącego destrukturyzjacji. Pojawia się tam przykład, który tłumaczy różnicę pomiędzy arguments a ...
czyli operatorem reszty.
# Rest - destrukturyzacja
Jak działa rest?
function show( x, y, ...args ) {
console.log( x, y, args );
}
show(); //undefined undefined []
show( 1, 2, 3, 4, 5, 6); //1 2 [3, 4, 5, 6]
jak widzimy, argumenty nie przypisane do odpowiadającym im zmiennych, wchodzą w skład tablicy args
.
To teraz proste zadanie, z którym miałem okazję zetknąć się przy zgłębianiu tajników języka Prolog. Użytkownik może podać dowolną ilość argumentów, z zaznaczeniem że ich minimalna ilość to 2. Zadaniem funkcji jest zwrócić tablicę z argumentami, jednak argument podany jako pierwszy ma znajdować się na jej samym końcu.
const shift = (head, ...tail) => [tail, head];
shift(1,2,3); //[2, 3, 1]
# Argumenty domyślne i tablica argumentów
Dzięki tablicy argumentów, możemy odwoływać się do poszczególnych argumentów oraz wykonywać na niej inne funkcje takie jak np. filter
. Nie musimy także określać ilości przekazywanych argumentów. Jest jeszcze jedna funkcjonalność dodana w ES6, o której jeszcze nie wspominaliśmy na tym blogu, a mianowicie - argument domyślny, czyli taki, który ustawiamy, jeśli argumentów będzie mniej niż oczekujemy.
function show(y, x = 2){
console.log(y * x);
}
show(2); //4
show(2, 3); //6
Wcześniej musieliśmy sobie radzić z argumentem domyślnym w taki sposób:
function show(y, x) {
x = x || 2;
console.log(y * x);
}
# Purity - czyste funkcje
W programowaniu funkcyjnym powinniśmy trzymać się w miarę możliwości zasady czystości funkcji.
Funkcja powinna być prosta i przyjmować argumenty, w innym wypadku byłaby bezużyteczna. Czyste funkcje, nie powinny modyfikować zmiennych spoza swojego zasięgu i zmiennych globalnych, dlatego muszą zwracać jakąś wartość. Dzięki prostocie tych funkcji możemy zwiększać reusability kodu zgodnie z zasadą KISS, czyli Keep It Simple, Stupid. Nasze programy staną się łatwiejsze do późniejszej modyfikacji. Funkcje, które modyfikują lub operują na zmiennych spoza swojego zasięgu mają efekt uboczny - nie zawsze zwracają przewidywalny wynik. Czysta funkcja musi zwrócić zawsze ten sam wynik dla takich samych wartości. Oczywiście nie da się wyeliminować całkowicie funkcji, które nie są czyste, ale w miarę możliwości powinniśmy starać się ich unikać.