Funcția Currying în Swift

Introducere

Currying este o caracteristică găsită în cele mai moderne limbi de programare. Transcrie o singură funcție cu mai multe argumente într-o serie de funcții fiecare cu un singur argument. În esență, acest lucru permite stocarea funcțiilor în variabile și crearea funcțiilor care returnează funcțiile.

Deși poate părea la început un concept ciudat, este o tehnică puternică care uneori poate fi foarte utilă. În acest tutorial, vă voi arăta cum să profitați de funcția currying în Swift.

1. Funcția de curățare cu clase

Înainte de a ne defini funcțiile personalizate, vă voi arăta mai întâi un exemplu simplu de currying în Swift folosind clase.

Deschideți Xcode, creați un nou loc de joacă iOS sau OS X și adăugați următorul cod:

clasa Mașină var speed = 0 func accelerateBy (factor: Int) -> Int viteză + = viteza de întoarcere factor let car1 = Mașină

Definim o clasă de bază cu o singură metodă sau funcție de proprietate și o instanță. De asemenea, creăm o instanță a clasei, auto1. Putem să sunăm accelerateBy (_ :) metoda noastră Mașină exemplu cu următorul cod:

car1.accelerateBy (10)

Există, totuși, un alt mod de a executa această metodă prin utilizarea funcției currying. În exemplul de mai sus, numiți direct metoda auto1 în ciuda faptului că metoda este definită în realitate Mașină clasă. Metoda pe care am scris-o nu este specifică pentru auto1 exemplu, ci mai degrabă Mașină clasă. Când numiți această metodă, ceea ce se întâmplă cu adevărat este că Swift intră mai întâi la Mașină clasă, returnează accelerateBy (_ :) , indică metoda care instanță este utilizată și apoi execută o metodă modificată specifică acelei instanțe. Pentru a vă arăta cum funcționează, adăugați următoarea linie la locul de joacă:

Car.accelerateBy (auto1)

Ceea ce facem aici este accesarea accelerateBy (_ :) metodă a Mașină clasa și trecerea, ca parametru, care instanță dorim ca această funcție să fie executată. În bara laterală a locului de joc, puteți vedea că rezultatul acestei metode este o altă funcție.

Ce acest (Funcţie) rezultatul reprezintă este de fapt unul nou accelerateBy (_ :) metodă specifică auto1 instanță. Această funcție returnată este unică prin faptul că se referă în mod specific auto1„s viteză mai degrabă decât metoda generică pe care ați definit-o mai devreme, care poate face referire la viteză proprietatea oricarui Mașină instanță.

După cum v-ați aștepta, putem transmite parametri noi acestei funcții returnate pentru a le executa așa cum facem de obicei. Adăugați următoarea linie de cod la locul de joacă:

Car.accelerateBy (auto1) (10)

Cu acest cod, trecem 10 ca parametru în unic accelerateBy (_ :) și obțineți auto1viteza actuală a revenit ca rezultat.

Felicitări! Tocmai ai profitat de funcția currying în Swift pentru prima dată.

În plus față de currying împreună funcții multiple, Fcucernicie Rezultatul că codul dvs. se întoarce poate fi, de asemenea, stocat într-o variabilă. Acest lucru vă permite să stocați și să reutilizați repede accelerateBy (_ :) metoda specifică pentru dvs. auto1 instanță. Adăugați următoarele linii la locul de joacă:

Fie a = Car.accelerateBy (car1) a (10) a (20) a (30)

Puteți vedea acea variabilă A acum se comportă ca orice altă funcție definită la nivel global. Avantajul este că este specific unui anumit Mașină exemplu, care poate fi definit la timpul de execuție, mai degrabă decât timpul de compilare. În loc de joacă, puteți vedea ieșirile așteptate afișate în bara laterală.

În cele din urmă, vă voi arăta cum puteți reveni la o funcție de la o altă funcție prin reimplementarea comportamentului Mașină clasa pe care tocmai am privit-o. Vom face acest lucru prin definirea unei funcții care returnează o altă funcție. În codul dvs., această funcție ar putea arăta astfel:

funcfunFunction (intrare: AnyObject) -> (AnyObject) -> AnyObject // Efectuați lucruri pentru a returna o funcție 

Definim someFunction (_ :) funcție, care acceptă o AnyObject parametru și returnează o altă funcție care acceptă și o funcție AnyObject parametru care returnează un AnyObject rezultat. Acest tip de definiție a funcției poate părea foarte confuz și descurajator la început. Pentru ao simplifica, putem profita de typealias cuvânt cheie din Swift pentru a mapa un nume nou la orice tip de date.

Adăugați următorul cod la locul de joacă:

(Intr) - IntFunction IntFunction = (int) -> Int func accelerationForCar (masina: Masina) -> IntFunction retur Car.accelerateBy (masina) let newA = accelerationForCar (car1) newA (10)

Prin utilizarea typealias pentru a marca numele IntFunction la (Int) -> Int tip de date, am simplificat foarte mult accelerationForCar (_ :) funcție de definiție. (Int) -> Int tipul de date reprezintă pur și simplu o funcție care acceptă o Int parametru și returnează un Int valoare.

Această nouă funcție utilizează comportamentul încorporat al Mașină clasa pentru a reveni un IntFunction obiect care poate fi apoi stocat într-o variabilă și folosit ca și înainte.

2. Curățarea funcțiilor personalizate

În timp ce comportamentul încorporat în Swift este foarte util, puteți să vă creați propriile funcții care nu sunt legate de clase. Pentru această parte a tutorialului, vom folosi mai întâi exemplul unei funcții care înmulțește un alt număr cu o valoare constantă.

Imaginați-vă că doriți să creați o funcție care acceptă un singur număr de intrare și se multiplică cu 5. Această funcție simplă ar putea arăta astfel:

func multiplyBy5 (a: Int) -> Int return a * 5

Acum, imaginați-vă că aveți nevoie de o funcție similară, dar aveți nevoie să se înmulțească cu 10, mai degrabă decât 5. Apoi, aveți nevoie de o altă funcție de multiplicat cu 20. În timp ce ați putea crea trei funcții similare și le numiți multiplyBy5multiplyBy10, și multiplyBy20, acest lucru ar putea fi manipulat mult mai bine folosind funcția de currying.

Adăugați următorul fragment de cod la locul de joacă:

(int: int) -> Int return a * b return nestedMultiply multiplyBy (10) (20) let multiplyBy5 = multiplyBy (5) multiplyBy5 (4)

Definim înmulțit cu(_:) funcție care acceptă o Int ca singurul său parametru și returnează o funcție de tip IntFunction, tipul de date pe care l-am definit mai devreme în acest tutorial. În această funcție, definim o altă funcție, nestedMultiply (_ :). Am plasat această funcție în primul rând astfel încât să nu poată fi executat în afara domeniului înmulțit cu(_:) funcționează și are acces la A parametru de intrare.

Cele trei rânduri de sub definiția funcției sunt simple exemple de cum puteți să colați împreună funcțiile.

În timp ce puteți crea funcții pentru currying folosind funcții imbricate, le puteți crea, de asemenea, utilizând închideri sau prin definirea mai multor seturi de parametri. De exemplu, adăugați următorul fragment de cod la locul de joacă:

(a: int) -> IntFunction return b in a + b sa adauge2 = add (2) add2 (4) a a scădea subtract5 = scădea (5) scădea5 (b: 8)

După cum puteți vedea, aceste două noi funcții pot fi curridate împreună, la fel ca toate celelalte funcții care au existat în acest tutorial. Singura excepție este că, cu funcția definită cu două seturi de parametri, trebuie să denumiți în mod explicit al doilea parametru.

Nu există nicio limită a numărului de niveluri de funcție de currying pe care le puteți implementa în cadrul codului. Următorul cod prezintă un exemplu de trei funcții curried și modul în care acesta diferă de-a lungul unei singure funcții cu trei parametri.

Functia multiplica (a: int, b: int, c: int) -> int return a * b * c func multiplica (int: > IntFunction func nestedMultiply2 (c: Int) -> int return a * b * c return nestedMultiply2 return nestedMultiply1 multiplica (4, 5,

Principala diferență dintre aceste două funcții de multiplicare este aceea că versiunea curried poate fi efectiv întreruptă și stocată într-o variabilă după ce primul sau al doilea parametru a fost procesat. Acest lucru face ca funcția să fie foarte ușor de reutilizat și să treacă drept obiect.

Concluzie

Funcția de curtare în Swift este un concept dificil de înțeles, dar, în esență, este în esență despre două concepte-cheie:

  • crearea de funcții care returnează alte funcții
  • reducerea funcțiilor cu mai multe argumente într-o serie de funcții fiecare cu un singur argument

Există o varietate de moduri de a curry funcțiile împreună și, în timp ce numai Int tipul de date a fost folosit în acest tutorial, aceleași procese pot fi utilizate cu orice tip de date în proiectele Swift. Acest lucru permite ca funcțiile să fie stocate în variabile și să fie utilizate de mai multe ori în întregul cod.

Ca întotdeauna, vă rugăm să aveți grijă să lăsați comentariile și comentariile dvs. mai jos în comentarii.

Cod