Il currying è una funzionalità che si trova nella maggior parte dei moderni linguaggi di programmazione. Traduce una singola funzione con più argomenti in una serie di funzioni ognuna con un argomento. In sostanza, ciò consente di memorizzare funzioni in variabili e creare funzioni che restituiscono funzioni.
Sebbene possa sembrare un concetto strano all'inizio, è una tecnica potente che può essere molto utile a volte. In questo tutorial, ti mostrerò come sfruttare la funzione di curriculum in Swift.
Prima di definire le nostre funzioni personalizzate, per prima cosa ti mostrerò un semplice esempio di curriculum in Swift usando le classi.
Apri Xcode, crea un nuovo parco giochi iOS o OS X e aggiungi il seguente codice:
class Car var speed = 0 func accelerateBy (factor: Int) -> Int velocità + = fattore di velocità di ritorno lascia car1 = Car ()
Definiamo una classe base con una proprietà e un metodo o una funzione di istanza. Creiamo anche un'istanza della classe, car1
. Possiamo chiamare il accelerateBy (_ :)
metodo del nostro Auto
istanza con il seguente codice:
car1.accelerateBy (10)
Esiste, tuttavia, un altro modo di eseguire questo metodo attraverso l'uso della funzione currying. Nell'esempio precedente, si chiama direttamente il metodo car1
nonostante il metodo sia effettivamente definito nel Auto
classe. Il metodo che abbiamo scritto non è specifico per car1
esempio, ma piuttosto il Auto
classe. Quando chiami questo metodo, quello che sta realmente accadendo è che Swift prima va al Auto
classe, recupera il accelerateBy (_ :)
metodo, indica al metodo quale istanza viene utilizzata e quindi esegue un metodo modificato specifico per quell'istanza. Per mostrarti come funziona, aggiungi la seguente riga al tuo parco giochi:
Car.accelerateBy (car1)
Quello che stiamo facendo qui è l'accesso al accelerateBy (_ :)
metodo del Auto
class e passa, come parametro, su quale istanza vogliamo che questa funzione sia eseguita. Nella barra laterale del tuo parco giochi, puoi vedere che il risultato di questo metodo è un'altra funzione.
Che cosa (Funzione) il risultato rappresenta è in realtà un nuovo accelerateBy (_ :)
metodo specifico per car1
esempio. Questa funzione restituita è unica nel suo specifico riferimento car1
'S velocità
proprietà piuttosto che il metodo generico definito in precedenza, che può fare riferimento a velocità
proprietà di alcuno Auto
esempio.
Come ci si aspetterebbe, possiamo passare nuovi parametri a questa funzione restituita per eseguirla come facciamo di solito. Aggiungi la seguente riga di codice al tuo campo di gioco:
Car.accelerateBy (car1) (10)
Con questo codice, passiamo 10
come parametro nell'unico accelerateBy (_ :)
metodo e ottenere car1
La velocità corrente è tornata come risultato.
Congratulazioni! Hai appena approfittato della funzione di curriculum in Swift per la prima volta.
Oltre a far coesistere più funzioni, il Funzione risultato che il tuo codice sta ritornando può anche essere memorizzato in una variabile. Ciò consente di archiviare e riutilizzare rapidamente il file accelerateBy (_ :)
metodo specifico per il tuo car1
esempio. Aggiungi le seguenti linee al tuo parco giochi:
lascia a = Car.accelerateBy (car1) a (10) a (20) a (30)
Puoi vedere quella variabile un
ora si comporta come qualsiasi altra funzione definita globalmente. Il vantaggio è che è specifico per un particolare Auto
istanza, che può essere definita in fase di esecuzione anziché in fase di compilazione. Nel tuo parco giochi, puoi vedere gli output attesi visualizzati nella barra laterale.
Infine, ti mostrerò come è possibile restituire una funzione da un'altra funzione reimplementando il comportamento di Auto
classe che abbiamo appena visto. Lo faremo definendo una funzione che restituisce un'altra funzione. Nel tuo codice, questa funzione potrebbe essere simile a questa:
func someFunction (input: AnyObject) -> (AnyObject) -> AnyObject // Fai qualcosa per restituire una funzione
Definiamo il someFunction (_ :)
funzione, che accetta un ANYOBJECT
parametro e restituisce un'altra funzione che accetta anche un ANYOBJECT
parametro che restituisce un ANYOBJECT
risultato. All'inizio questo tipo di definizione di funzione può sembrare molto confuso e scoraggiante. Per semplificarlo, possiamo sfruttare il typealias
parola chiave in Swift per mappare un nuovo nome per qualsiasi tipo di dati.
Aggiungi il seguente codice al tuo parco giochi:
typealias IntFunction = (Int) -> Int func accelerationForCar (car: Car) -> IntFunction return Car.accelerateBy (car) let newA = accelerationForCar (car1) newA (10)
Usando typealias
per mappare il nome di IntFunction
al (Int) -> Int
tipo di dati, abbiamo notevolmente semplificato il accelerationForCar (_ :)
definizione della funzione. Il (Int) -> Int
tipo di dati rappresenta semplicemente una funzione che accetta un Int
parametro e restituisce un Int
valore.
Questa nuova funzione utilizza il comportamento predefinito di Auto
classe per restituire un IntFunction
oggetto che può quindi essere memorizzato in una variabile e utilizzato come prima.
Mentre la funzione incorporata che sta eseguendo il comportamento di Swift è molto utile, potresti voler creare le tue funzioni che non sono correlate alle classi. Per questa parte del tutorial, per prima cosa utilizzeremo l'esempio di una funzione che moltiplica un altro numero per un valore costante.
Immagina di voler creare una funzione che accetti un singolo numero di input e la moltiplichi per 5. Questa semplice funzione potrebbe assomigliare a questa:
func multiplyBy5 (a: Int) -> Int return a * 5
Ora immagina di aver bisogno di una funzione simile, ma ne hai bisogno per moltiplicare per 10 anziché per 5. Quindi hai bisogno di un'altra funzione per moltiplicare per 20. Mentre potresti creare tre funzioni simili e nominarle multiplyBy5
, multiplyBy10
, e multiplyBy20
, questo potrebbe essere gestito molto meglio usando la funzione currying.
Aggiungi il seguente snippet di codice al tuo campo di gioco:
func multiplyBy (a: Int) -> IntFunction func nestedMultiply (b: Int) -> Int return a * b return nestedMultiply multiplyBy (10) (20) let multiplyBy5 = multiplyBy (5) multiplyBy5 (4)
Definiamo il moltiplicato per(_:)
funzione che accetta un Int
come unico parametro e restituisce una funzione di tipo IntFunction
, il tipo di dati che abbiamo definito in precedenza in questo tutorial. In questa funzione, definiamo un'altra funzione, nestedMultiply (_ :)
. Annidiamo questa funzione nel primo modo che non possa essere eseguita al di fuori dell'ambito del moltiplicato per(_:)
funzione e ha accesso al un
parametro di input.
Le tre linee sotto la definizione della funzione sono semplici esempi di come è possibile combinare insieme le funzioni.
Mentre è possibile creare funzioni per la conversione utilizzando funzioni nidificate, è anche possibile crearle utilizzando chiusure o definendo più gruppi di parametri. Ad esempio, aggiungi il seguente snippet di codice al tuo campo di gioco:
func add (a: Int) -> IntFunction return b in a + b lascia add2 = add (2) add2 (4) func sottrazione (a: Int) (b: Int) -> Int return b - a lascia sottrarre 5 = sottrarre (5) sottrarre 5 (b: 8)
Come puoi vedere, queste due nuove funzioni possono essere riunite insieme nello stesso modo in cui tutte le altre funzioni sono state incluse in questo tutorial. L'unica eccezione è che, con la funzione definita con due serie di parametri, è necessario nominare esplicitamente il secondo parametro.
Non c'è limite al numero di livelli di funzione che è possibile implementare nel codice. Il codice seguente mostra un esempio di tre funzioni al curry e il modo in cui differisce su una singola funzione con tre parametri.
func moltiplicare (a: Int, b: Int, c: Int) -> Int return a * b * c func multiplo (a: Int) -> (Int) -> IntFunction func nestedMultiply1 (b: Int) - > IntFunction func nestedMultiply2 (c: Int) -> Int return a * b * c return nestedMultiply2 return nestedMultiply1 multiply (4, 5, 6) multiply (4) (5) (6)
La principale differenza tra queste due funzioni di moltiplicazione è che la versione al curry può essere effettivamente messa in pausa e memorizzata in una variabile dopo che il primo o il secondo parametro sono stati elaborati. Questo rende la funzione molto facile da riutilizzare e passare in giro come un oggetto.
La funzione di curriculum in Swift è un concetto difficile da comprendere, ma, in sostanza, si basa essenzialmente su due concetti chiave:
Ci sono una varietà di modi per curry funzioni insieme e, mentre solo il Int
tipo di dati è stato utilizzato in questo tutorial, gli stessi processi possono essere utilizzati con qualsiasi tipo di dati nei progetti Swift. Ciò consente di memorizzare le funzioni in variabili e di essere utilizzate più volte nel codice.
Come sempre, si prega di essere sicuri di lasciare i vostri commenti e feedback qui sotto nei commenti.