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.
Î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 auto1
viteza 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.
Î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 multiplyBy5
, multiplyBy10
, ș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.
Funcția de curtare în Swift este un concept dificil de înțeles, dar, în esență, este în esență despre două concepte-cheie:
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.