Funksjon Currying i Swift

Introduksjon

Currying er en funksjon som finnes i de fleste moderne programmeringsspråk. Den oversetter en enkelt funksjon med flere argumenter til en serie funksjoner hver med ett argument. Dette gjør det i hovedsak mulig å lagre funksjoner i variabler og skape funksjoner som returnerer funksjoner.

Selv om det kan virke som et merkelig konsept i begynnelsen, er det en kraftig teknikk som kan være svært nyttig til tider. I denne opplæringen skal jeg vise deg hvordan du kan dra nytte av funksjon currying i Swift.

1. Funksjon Currying med klasser

Før du definerer våre egne tilpassede funksjoner, skal jeg først vise deg et enkelt eksempel på currying i Swift ved hjelp av klasser.

Åpne Xcode, opprett en ny iOS- eller OS X-lekeplass, og legg til følgende kode for det:

klasse car var hastighet = 0 func accelerateBy (faktor: Int) -> Int speed + = faktor returhastighet la car1 = Bil ()

Vi definerer en grunnklass med en egenskap og en forekomstsmetode eller -funksjon. Vi lager også en forekomst av klassen, akkumulatorer1. Vi kan ringe til accelerateBy (_ :) metode for vår Bil eksempel med følgende kode:

car1.accelerateBy (10)

Det er imidlertid en annen måte å utføre denne metoden ved hjelp av funksjon currying. I eksempelet ovenfor kaller du metoden direkte på akkumulatorer1 til tross for at metoden faktisk er definert i Bil klasse. Metoden vi har skrevet er ikke spesifikk for akkumulatorer1 eksempel, men snarere Bil klasse. Når du ringer denne metoden, er det som virkelig skjer, at Swift først går til Bil klasse, henter accelerateBy (_ :) metode, forteller hvilken metode som brukes, og utfører deretter en endret metode som er spesifikk for den forekomsten. For å vise deg hvordan dette virker, legg til følgende linje på lekeplassen din:

Car.accelerateBy (akkumulatorer1)

Det vi gjør her er å få tilgang til accelerateBy (_ :) metode av Bil klasse og passerer, som en parameter, hvilken forekomst vi vil at denne funksjonen skal utføres på. I lekeplassens sidefelt kan du se at resultatet av denne metoden er en annen funksjon.

Hva er dette (Funksjon) Resultatet representerer er faktisk en ny accelerateBy (_ :) metode spesifikk for akkumulatorer1 forekomst. Denne returnerte funksjonen er unik ved at den spesifikt refererer til akkumulatorer1's hastighet eiendom i stedet for generisk metode du definerte tidligere, som kan referere til hastighet eiendom av noen Bil forekomst.

Som du forventer, kan vi sende nye parametere til denne returnerte funksjonen for å utføre den som vi vanligvis gjør. Legg til følgende linje med kode til lekeplassen din:

Car.accelerateBy (akkumulatorer1) (10)

Med denne koden passerer vi 10 som en parameter i den unike accelerateBy (_ :) metode og få akkumulatorer1Nåværende hastighet returneres som et resultat.

Gratulerer! Du har nettopp utnyttet funksjon currying i Swift for aller første gang.

I tillegg til å currying sammen flere funksjoner, den Function Resultatet at koden din er tilbake kan også lagres i en variabel. Dette gjør at du kan lagre og raskt gjenbruke accelerateBy (_ :) metode spesifikk for din akkumulatorer1 forekomst. Legg til følgende linjer på lekeplassen din:

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

Du kan se den variabelen en Nå oppfører seg som enhver annen globalt definert funksjon. Fordelen er at den er spesifikk for en bestemt Bil eksempel, som kan defineres på kjøretid i stedet for kompileringstid. På lekeplassen kan du se de forventede utgangene som vises i sidefeltet.

Til slutt skal jeg vise deg hvordan du kan returnere en funksjon fra en annen funksjon ved å reimplementere oppførselen til Bil klasse som vi nettopp har sett på. Vi skal gjøre dette ved å definere en funksjon som returnerer en annen funksjon. I koden din kan denne funksjonen se slik ut:

func someFunction (input: AnyObject) -> (AnyObject) -> AnyObject // Gjør ting for å returnere en funksjon 

Vi definerer someFunction (_ :) funksjon, som aksepterer en AnyObject parameter og returnerer en annen funksjon som også aksepterer en AnyObject parameter som returnerer en AnyObject resultat. Denne typen funksjonsdefinisjon kan se veldig forvirrende og skremmende i starten. For å forenkle det kan vi dra nytte av typealias søkeord i Swift for å kartlegge et nytt navn til en hvilken som helst datatype.

Legg til følgende kode på lekeplassen din:

type AI (Int) => Int> Funksjonalitet (Car)>> IntFunksjon Return Car.accelerateBy (bil) la newA = accelerationForCar (car1) newA (10)

Ved bruk av typealias å kartlegge navnet på IntFunction til (Int) -> Int datatype, har vi sterkt forenklet accelerationForCar (_ :) funksjonsdefinisjon. De (Int) -> Int datatype representerer bare en funksjon som aksepterer en int parameter og returnerer en int verdi.

Denne nye funksjonen bruker den innebygde oppførselen til Bil klasse for å returnere en IntFunction objekt som kan lagres i en variabel og brukes som vi gjorde før.

2. Currying Custom Funksjoner

Mens den innebygde funksjonen currying atferd i Swift er veldig nyttig, kan du ønske å lage dine egne funksjoner som ikke er relatert til klasser. For denne delen av opplæringen skal vi først bruke eksemplet på en funksjon som multipliserer et annet tall med en konstant verdi.

Tenk deg at du vil opprette en funksjon som aksepterer et enkelt inngangsnummer og multipliserer det med 5. Denne enkle funksjonen kan se slik ut:

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

Forestill deg nå at du trenger en lignende funksjon, men du trenger den til å formere med 10 i stedet for 5. Da trenger du en annen funksjon til å formere med 20. Mens du kan lage tre lignende funksjoner og nevne dem multiplyBy5multiplyBy10, og multiplyBy20, dette kan håndteres mye bedre ved å bruke funksjon currying.

Legg til følgende kodestykke til lekeplassen din:

func multiplyBy (a: Int) -> IntFunction func nestedMultiply (b: Int) -> Int return a * b return nestedMultiply multiplyBy (10) (20) la multiplyBy5 = multiplyBy (5) multiplyBy5 (4)

Vi definerer multiplyBy (_ :) funksjon som aksepterer en int som den eneste parameteren og returnerer en funksjon av typen IntFunction, Datatypen vi definerte tidligere i denne opplæringen. I denne funksjonen definerer vi en annen funksjon, nestedMultiply (_ :). Vi nest denne funksjonen innen den første slik at den ikke kan utføres utenfor omfanget av multiplyBy (_ :) funksjon og har tilgang til en inngangsparameter.

De tre linjene under funksjonsdefinisjonen er enkle eksempler på hvordan du kan curry funksjonene sammen.

Mens du kan lage funksjoner for currying ved hjelp av nestede funksjoner, kan du også opprette dem ved hjelp av nedleggelser eller ved å definere flere sett med parametere. For eksempel, legg til følgende kodestykke til lekeplassen din:

func add (a: Int) -> IntFunction return b i a + b la add2 = add (2) add2 (4) func subtrahere (a: Int) (b: Int) -> Int return b - a la subtract5 = subtrahere (5) subtrahere5 (b: 8)

Som du kan se, kan disse to nye funksjonene bli kurert sammen på samme måte som alle de andre funksjonene har vært gjennom hele denne opplæringen. Det eneste unntaket er at med funksjonen definert med to sett med parametere, må du eksplisitt kjenne den andre parameteren.

Det er ingen grense for antall nivåer av funksjon currying du kan implementere innenfor koden din. Følgende kode viser et eksempel på tre curried funksjoner og hvordan det adskiller seg over en enkelt funksjon med tre parametere.

func multiply (a: Int, b: Int, c: Int) -> Int return a * b * c func multipliserer (a: Int) -> (Int) -> IntFunction func nestedMultiply1 (b: Int) > IntFunction func nestedMultiply2 (c: Int) -> Int return a * b * c returner nestedMultiply2 retur nestedMultiply1 multiply (4, 5, 6) multiply (4) (5)

Hovedforskjellen mellom disse to multiplikasjonsfunksjonene er at den curried versjonen effektivt kan stoppes og lagres i en variabel etter at den første eller andre parameter har blitt behandlet. Dette gjør funksjonen veldig lett å gjenbruke og overføre som et objekt.

Konklusjon

Funksjon currying i Swift er et vanskelig konsept å forstå, men i kjernen er det i utgangspunktet om to sentrale begreper:

  • skaper funksjoner som returnerer andre funksjoner
  • reduserer funksjoner med flere argumenter til en rekke funksjoner, hver med ett argument

Det finnes en rekke måter å curryfunksjoner sammen og, mens bare int Datatype ble brukt i denne opplæringen, de samme prosessene kan brukes med hvilken som helst datatype i Swift-prosjektene. Dette gjør at funksjonene kan lagres i variabler og brukes mange ganger i hele koden.

Som alltid, vær så snill å legge igjen dine kommentarer og tilbakemelding nedenfor i kommentarene.