Usamos cookies para mejorar tu experiencia en el sitio
CodeWorlds

Czym jest programowanie funkcyjne?

Wyobraź sobie laboratorium w Parku Jurajskim, w którym każdy eksperyment na DNA dinozaura daje zawsze ten sam rezultat przy tych samych danych wejściowych. Nie ma żadnych efektów ubocznych - żaden dinozaur nie ucieka, żaden system bezpieczeństwa nie zostaje przypadkowo wyłączony. Dokładnie tak działa programowanie funkcyjne (FP) - to paradygmat, w którym kod zachowuje się jak kontrolowany eksperyment naukowy.

Paradygmat funkcyjny vs imperatywny

W programowaniu imperatywnym mówimy komputerowi jak ma coś zrobić krok po kroku. W programowaniu funkcyjnym opisujemy co chcemy osiągnąć, używając funkcji jako podstawowych jednostek budulcowych.

1// Podejście imperatywne - krok po kroku
2const dinosaurs = ['T-Rex', 'Velociraptor', 'Triceratops', 'Stegosaurus'];
3const carnivores = [];
4for (let i = 0; i < dinosaurs.length; i++) {
5  if (dinosaurs[i] === 'T-Rex' || dinosaurs[i] === 'Velociraptor') {
6    carnivores.push(dinosaurs[i]);
7  }
8}
9
10// Podejście funkcyjne - deklaratywne
11const isCarnivore = (name) => ['T-Rex', 'Velociraptor'].includes(name);
12const carnivoresFP = dinosaurs.filter(isCarnivore);

Czyste funkcje (Pure Functions)

Czysta funkcja to kontrolowany eksperyment - przy tych samych danych wejściowych zawsze zwraca ten sam wynik i nie powoduje żadnych efektów ubocznych.

Zasady czystej funkcji:

  1. Determinizm - ten sam input = ten sam output, zawsze
  2. Brak efektów ubocznych - nie modyfikuje niczego poza swoim zakresem
1// CZYSTA FUNKCJA - zawsze ten sam wynik
2function calculateDangerLevel(weight, speed, aggression) {
3  return (weight * 0.3) + (speed * 0.3) + (aggression * 0.4);
4}
5
6// Ta sama funkcja wywolana 1000 razy z tymi samymi argumentami
7// zawsze zwroci ten sam wynik
8calculateDangerLevel(8000, 40, 95); // zawsze 2465
9calculateDangerLevel(8000, 40, 95); // zawsze 2465
10
11// NIECZYSTA FUNKCJA - modyfikuje dane zewnetrzne
12let totalDinosaurs = 0;
13function addDinosaur(name) {
14  totalDinosaurs++; // efekt uboczny - zmienia zmienna zewnetrzna!
15  return { name, id: totalDinosaurs };
16}
17// Kazde wywolanie daje inny wynik, nawet z tym samym argumentem
18addDinosaur('Rex'); // { name: 'Rex', id: 1 }
19addDinosaur('Rex'); // { name: 'Rex', id: 2 } - inny wynik!

Niemutowalność (Immutability)

Niemutowalność to zasada, że raz utworzone dane nigdy nie są zmieniane. Zamiast modyfikować istniejący obiekt, tworzymy nową kopię ze zmianami. To jak tworzenie nowej sekwencji DNA zamiast modyfikowania istniejącej - bezpieczniej i bardziej przewidywalnie.

1// MUTACJA - niebezpieczna (zmiana oryginalnego obiektu)
2const dinosaur = { name: 'Rex', health: 100 };
3dinosaur.health = 80; // Oryginaly obiekt zostal zmieniony!
4
5// NIEMUTOWALNOSC - bezpieczna (nowy obiekt)
6const dinosaurSafe = { name: 'Rex', health: 100 };
7const injuredDinosaur = { ...dinosaurSafe, health: 80 };
8// dinosaurSafe wciaz ma health: 100 (niezmieniony)
9// injuredDinosaur ma health: 80 (nowy obiekt)

Funkcje jako wartości pierwszoklasowe

W JavaScript funkcje są wartościami pierwszoklasowymi (first-class citizens) - możesz je przypisywać do zmiennych, przekazywać jako argumenty i zwracać z innych funkcji.

1// Funkcja przypisana do zmiennej
2const classify = (dino) => dino.diet === 'carnivore' ? 'dangerous' : 'safe';
3
4// Funkcja jako argument
5const dinosaurs = [
6  { name: 'Rex', diet: 'carnivore' },
7  { name: 'Brachio', diet: 'herbivore' },
8];
9const dangerous = dinosaurs.filter((dino) => classify(dino) === 'dangerous');
10
11// Funkcja zwracajaca funkcje
12function createValidator(minWeight) {
13  return (dino) => dino.weight >= minWeight;
14}
15const isHeavyDino = createValidator(5000);
16isHeavyDino({ weight: 8000 }); // true
17isHeavyDino({ weight: 200 });  // false
Ir a CodeWorlds