Programarea funcțională a fost o călătorie destul de deschisă pentru mine. Această postare, și postări ca aceasta, sunt o încercare de a-mi împărtăși perspectivele și perspectivele pe măsură ce parcurg noi terenuri de programare funcționale.

Al lui Ramda a fost biblioteca mea de acces la FP din cauza cât de ușor face programarea funcțională în JavaScript. Îl recomand cu drag.

Țeavă

Conceptul de pipe este simplu – se combină n funcții. Este o conductă care curge de la stânga la dreapta, apelând fiecare funcție cu ieșirea ultimei.

Să scriem o funcție care returnează a cuiva name.

getName = (person) => person.name;

getName({ name: 'Buckethead' });
// 'Buckethead'

Să scriem o funcție cu majuscule șiruri.

uppercase = (string) => string.toUpperCase();

uppercase('Buckethead');
// 'BUCKETHEAD'

Deci, dacă am vrea să obținem și să valorificăm personnumele lui, am putea face acest lucru:

name = getName({ name: 'Buckethead' });
uppercase(name);

// 'BUCKETHEAD'

Este în regulă, dar să eliminăm variabila intermediară name.

uppercase(getName({ name: 'Buckethead' }));

Mai bine, dar nu-mi place acest cuib. Poate deveni prea aglomerat. Ce se întâmplă dacă dorim să adăugăm o funcție care obține primele 6 caractere ale unui șir?

get6Characters = (string) => string.substring(0, 6);

get6Characters('Buckethead');
// 'Bucket'

Rezultând:

get6Characters(uppercase(getName({ name: 'Buckethead' })));

// 'BUCKET';

Să ne înnebunim cu adevărat și să adăugăm o funcție pentru a inversa șirurile.

reverse = (string) =>
  string
    .split('')
    .reverse()
    .join('');

reverse('Buckethead');
// 'daehtekcuB'

Acum avem:

reverse(get6Characters(uppercase(getName({ name: 'Buckethead' }))));
// 'TEKCUB'

Se poate obține un pic … mult.

Pipe la salvare!

În loc să blocăm funcțiile din cadrul funcțiilor sau să creăm o grămadă de variabile intermediare, haideți pipe toate lucrurile!

pipe(
  getName,
  uppercase,
  get6Characters,
  reverse
)({ name: 'Buckethead' });
// 'TEKCUB'

Arta pură. Este ca o listă de lucruri pe toate!

Să trecem prin el.

În scop demo, voi folosi un pipe implementarea de la una dintre Eric Elliott‘s articole de programare funcționale.

pipe = (...fns) => (x) => fns.reduce((v, f) => f(v), x);

Îmi place acest mic one-liner.

Folosind odihnă parametrii, vezi articolul meu despre asta, putem țevi n funcții. Fiecare funcție preia ieșirea celei anterioare și totul este redus ? la o singură valoare.

Și îl puteți folosi la fel cum am făcut mai sus.

pipe(
  getName,
  uppercase,
  get6Characters,
  reverse
)({ name: 'Buckethead' });
// 'TEKCUB'

Mă voi extinde pipe și adăugăm câteva instrucțiuni de depanare și vom merge rând cu rând.

pipe = (...functions) => (value) => {
  debugger;

  return functions.reduce((currentValue, currentFunction) => {
    debugger;

    return currentFunction(currentValue);
  }, value);
};

O introducere rapida la pipe si compose in

Apel pipe cu exemplul nostru și lăsați minunile să se desfășoare.

1611558425 943 O introducere rapida la pipe si compose in

Verificați variabilele locale. functions este o serie de 4 funcții și value este { name: 'Buckethead' }.

De când am folosit odihnă parametrii, pipe permite utilizarea oricărui număr de funcții. Se va bucla și le va chema pe fiecare.

1611558425 117 O introducere rapida la pipe si compose in

La următorul depanator, suntem înăuntru reduce. Aici e locul currentValue este trecut la currentFunction și s-a întors.

Vedem că rezultatul este 'Buckethead' deoarece currentFunction returnează .name proprietatea oricărui obiect. Aceasta va fi returnată în reduce, adică devine nou currentValue data viitoare. Să lovim următorul depanator și să vedem.

1611558425 21 O introducere rapida la pipe si compose in

Acum currentValue este ‘Buckethead’ pentru că asta s-a întors ultima dată. currentFunction este uppercase, asa de 'BUCKETHEAD' va fi următorul currentValue.

1611558426 151 O introducere rapida la pipe si compose in

Aceeași idee, smulge ‘BUCKETHEAD’primele 6 caractere și le predă la următoarea funcție.

1611558426 906 O introducere rapida la pipe si compose in

reverse(‘.aedi emaS’)

1611558426 234 O introducere rapida la pipe si compose in

Și gata!

Ce zici de compune ()?

E doar pipe în cealaltă direcție.

Deci, dacă vrei același rezultat ca al nostru pipe mai sus, ai face contrariul.

compose(
  reverse,
  get6Characters,
  uppercase,
  getName
)({ name: 'Buckethead' });

Observați cum getName este ultima în lanț și reverse este primul?

Iată o implementare rapidă a compose, din nou, prin amabilitatea Magical Eric Elliott, din același articol.

compose = (...fns) => (x) => fns.reduceRight((v, f) => f(v), x);

Voi lăsa să extind această funcție cu debuggere ca un exercițiu pentru tine. Joacă-te cu el, folosește-l, apreciază-l. Și cel mai important, distrează-te!