Ātrs ievads par pipe () un sacerēšanu () JavaScript

Funkcionālā programmēšana man ir bijis diezgan atvērts ceļojums. Šis ieraksts un tamlīdzīgi ziņojumi ir mēģinājums dalīties savās atziņās un perspektīvās, ceļojot pa jaunām funkcionālajām programmēšanas zemēm.

Ramda ir bijusi mana FP bibliotēka, jo daudz vieglāk tā padara funkcionālu programmēšanu JavaScript. Es to ļoti iesaku.

Caurule

Jēdziens pipeir vienkāršs - tas apvieno nfunkcijas. Tā ir caurule, kas plūst no kreisās uz labo pusi, katru funkciju izsaucot ar pēdējās izeju.

Uzrakstīsim funkciju, kas atdod kādam name.

getName = (person) => person.name; getName({ name: 'Buckethead' }); // 'Buckethead' 

Uzrakstīsim funkciju, kas lielo burtu virknes.

uppercase = (string) => string.toUpperCase(); uppercase('Buckethead'); // 'BUCKETHEAD' 

Tātad, ja mēs vēlētos iegūt personvārdu un izmantot to ar lielo burtu , mēs varētu to izdarīt:

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

Tas ir labi, bet novērsīsim šo starpposma mainīgo name.

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

Labāk, bet man nepatīk šī ligzdošana. Tas var kļūt pārāk pārpildīts. Ko darīt, ja mēs vēlamies pievienot funkciju, kas iegūst pirmās 6 virknes rakstzīmes?

get6Characters = (string) => string.substring(0, 6); get6Characters('Buckethead'); // 'Bucket' 

Rezultāts:

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

Apmeklēsimies ļoti traki un pievienosim funkciju stīgu maiņai.

reverse = (string) => string .split('') .reverse() .join(''); reverse('Buckethead'); // 'daehtekcuB' 

Tagad mums ir:

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

Tas var iegūt mazliet ... daudz.

Caurule glābšanai!

Tā vietā, lai traucētu funkcijas funkcijās vai izveidotu virkni starpposma mainīgo, pieņemsim pipevisas lietas!

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

Tīra māksla. Tas ir kā todo saraksts!

Sāksim tam cauri.

Demonstrācijas nolūkos es izmantošu piperealizāciju no viena no Ērika Eljota funkcionālās programmēšanas rakstiem.

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

Es mīlu šo mazo līnijpārvadātāju.

Izmantojot atpūtas parametrus, skatiet manu rakstu par to, mēs varam veikt nfunkcijas. Katra funkcija ņem iepriekšējās izejas rezultātu, un tas viss tiek samazināts ? uz vienu vērtību.

Un jūs varat to izmantot tāpat kā mēs to darījām iepriekš.

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

Es izvērsīšu pipeun pievienošu dažus atkļūdotāju paziņojumus, un mēs ejam pa rindai.

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

Zvaniet pipear mūsu piemēru un ļaujiet brīnumiem atklāties.

Pārbaudiet vietējos mainīgos. functionsir 4 funkciju masīvs un valueir { name: 'Buckethead' }.

Tā kā mēs izmantojām atpūtas parametrus, pipeļauj izmantot jebkuru funkciju skaitu. Tas vienkārši cilpa un piezvanīs katram.

Pie nākamā atkļūdotāja mēs esam iekšā reduce. Šeit tiek currentValuenodota currentFunctionun atgriezta.

Mēs redzam, ka rezultāts ir 'Buckethead'tāpēc, ka currentFunctionatgriež .namejebkura objekta īpašumu. Tas tiks atgriezts reduce, tas nozīmē, ka currentValuenākamreiz tas kļūs par jaunu . Sasitīsim nākamo atkļūdotāju un redzēsim.

Tagad tas currentValueir ‘Buckethead’tāpēc, ka pagājušajā reizē tas tika atgriezts. currentFunctionir uppercase, tāds 'BUCKETHEAD'būs arī nākamais currentValue.

Tā pati ideja, noplūkt ‘BUCKETHEAD’pirmās 6 rakstzīmes un nodot tās nākamajai funkcijai.

reverse(‘.aedi emaS’)

Un jūs esat pabeidzis!

Kā ir ar komponēšanu ()?

Tas ir tikai pipeotrā virzienā.

Tātad, ja jūs vēlaties tādu pašu rezultātu kā mūsu pipeiepriekš, jūs rīkotos tieši pretēji.

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

Ievērojiet, kā getNameķēdē ir pēdējais un reversepirmais?

Šeit ir ātra ieviešana compose, atkal pieklājīgi no maģiskā Ērika Eliota no tā paša raksta.

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

Šīs funkcijas paplašināšanu ar debuggers atstāšu jums kā vingrinājumu. Spēlējies ar to, izmanto to, novērtē to. Un pats galvenais, ir jautri!