Parametri In-Out

I parametri variabili, come abbiamo visto, possono essere modificati solo all’interno della funzione stessa. Se si desidera modificare il valore di un parametro e che tali modifiche persistano dopo che la chiamata della funzione è terminata, bisogna definire il parametro come parametro in-out.

Si dichiara un parametro e si antepone “inout ” al suo inizio. Un parametro in-out ha un valore che viene passato alla funzione, viene modificato nella funzione, e viene restituito dalla funzione con il valore originale modificato.

È possibile passare solo una variabile come argomento per un parametro in-out. Non è possibile passare una costante o un valore literal come argomento, perché le costanti letterali e non possono essere modificate. Puoi piazzare una e commerciale (&) direttamente prima del nome di una variabile quando si passa come argomento di un parametro inout, per indicare che può essere modificato dalla funzione.

Ecco un esempio di una funzione chiamata swapTwoInts:

func swapTwoInts(inout a: Int, inout b: Int) {
let temporaryA = a
a = b
b = temporaryA
}

La funzione swapTwoInts scambia tra di loro i valori di a e b. La funzione esegue lo scambio memorizzando il valore di una in una costante temporanea denominata temporaryA, assegnando il valore di b per una, e assegnando temporaryA a b.

È possibile chiamare la funzione swapTwoInts con due variabili di tipo int per scambiare i loro valori. Si noti che i nomi di someInt e anotherInt sono precedute da una e commerciale quando sono passati alla funzione swapTwoInts:

var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
println(“someInt is now \(someInt), and anotherInt is now \(anotherInt)”)
// prints “someInt is now 107, and anotherInt is now 3”

L’esempio sopra mostra che i valori originali di someInt e anotherInt vengono modificati dalla funzione swapTwoInts, anche se essi sono stati inizialmente definiti al di fuori della funzione.

Tipi di funzione

Ogni funzione ha un tipo specifico, composto dai tipi di parametri e il tipo di ritorno della funzione.

Per esempio:

func addTwoInts(a: Int, b: Int) -> Int {
return a + b
}
func multiplyTwoInts(a: Int, b: Int) -> Int {
return a * b
}

Questo esempio definisce due semplici funzioni matematiche chiamate addTwoInts e multiplyTwoInts. Queste funzioni, ciascuna per due valori Int,  restituiscono un valore int, che è il risultato di un’ operazione matematica.

Il tipo di entrambe queste funzioni è (Int, Int) -> Int. Questo può essere letto come:

“Un tipo di funzione che ha due parametri, di tipo Int, e che restituisce un valore di tipo int.”

Ecco un altro esempio, per una funzione senza parametri e valore di ritorno:

func printHelloWorld() {
println(“hello, world”)
}

Il tipo di questa funzione è () -> (), o “. Una funzione che non ha parametri, e restituisce Void”. Le funzioni che non specificano un valore di ritorno restituiscono sempre Void, che equivale a una tupla vuota, indicata come ().
Utilizzo dei tipi di funzione
È possibile utilizzare i tipi di funzione, proprio come qualsiasi altro tipo di Swift. Ad esempio, è possibile definire una costante o una variabile di un tipo di funzione e assegnare una funzione appropriata a tale variabile:

var mathFunction: (int, int) -> int = addTwoInts
Questo può essere letto come:

Definire una variabile chiamata mathFunction, che prende due valori Int e restituisce un valore Int. Impostare questa nuova variabile per fare riferimento alle addTwoInts della funzione chiamata.

La funzione addTwoInts ha lo stesso tipo di variabile mathFunction, e quindi questa assegnazione è consentita dal tipo stesso.

Ora è possibile chiamare la funzione assegnata con il nome mathFunction:

 

println(“Result: \(mathFunction(2, 3))”)
// prints “Result: 5”

Una funzione diversa con lo stesso tipo di corrispondenza può essere assegnata alla stessa variabile, come per i tipi non-funzionali:

mathFunction = multiplyTwoInts
println(“Result: \(mathFunction(2, 3))”)
// prints “Result: 6”

Come con qualsiasi altro tipo, si può lasciare a Swift il compito di dedurre il tipo quando si assegna una funzione ad una costante o variabile:

anotherMathFunction = addTwoInts
// AnotherMathFunction si deduce essere di tipo (int, int) -> int

Tipi di funzione come tipi di parametri
È possibile utilizzare un tipo di funzione come (int, int) -> int come tipo di parametro per un’altra funzione.

Ecco un esempio che stampa i risultati delle funzioni matematiche di cui sopra:

func printMathResult(mathFunction: (Int, Int) -> Int, a: Int, b: Int) {
println(“Result: \(mathFunction(a, b))”)
}
printMathResult(addTwoInts, 3, 5)
// prints “Result: 8”

Questo esempio definisce una funzione chiamata printMathResult, che ha tre parametri. Il primo parametro è chiamato mathFunction, ed è di tipo (int, int) -> Int. È possibile passare qualsiasi funzione di quel tipo come argomento di questo primo parametro. Il secondo e il terzo parametro sono chiamati a e b, e sono di tipo Int. Questi sono usati come i due valori di ingresso per la funzione matematica.

Quando printMathResult viene chiamata, si passa alla funzione addTwoInts, processando i valori 3 e 5. Si chiama la funzione fornita con i valori 3 e 5, e stampa il risultato di 8.

Il ruolo di printMathResult è di stampare il risultato di una chiamata sottoforma di una funzione matematica di tipo adeguato.

Tipi di funzione come tipi di ritorno
È possibile utilizzare un tipo di funzione come tipo di ritorno di un’altra funzione. A tale scopo, scrivendo un tipo di funzione completo subito dopo la freccia di ritorno (->) della funzione di ritorno.

Il prossimo esempio definisce due funzioni semplici chiamate stepForward e stepbackward. La funzione stepForward restituisce un valore maggiorato di uno rispetto al suo valore di ingresso, e la funzione stepbackward restituisce il valore d’ingresso sottratto di uno. Entrambe le funzioni hanno un tipo di (Int) -> Int:

func stepForward(input: Int) -> Int {
return input + 1
}
func stepBackward(input: Int) -> Int {
return input – 1
}

Ecco una funzione chiamata chooseStepFunction, il cui tipo di ritorno è “una funzione di tipo (Int) -> Int”. chooseStepFunction restituisce la funzione stepForward o la funzione stepbackward sulla base di un parametro booleano denominato Forward:

func chooseStepFunction (indietro: Bool) -> (Int) -> int {
tornare indietro? stepbackward: stepForward
}

È ora possibile utilizzare chooseStepFunction per ottenere una funzione che farà un passo in una direzione o l’altra (avanti o indietro):

var currentValue = 3
let moveNearerToZero = chooseStepFunction(currentValue > 0)
// moveNearerToZero now refers to the stepBackward() function

L’esempio precedente funziona se un passo positivo o negativo è necessario per spostare una variabile chiamata CurrentValue progressivamente più vicino allo zero. CurrentValue ha un valore iniziale di 3, il che significa che CurrentValue> 0 restituisce TRUE, causando chooseStepFunction per tornare alla funzione stepbackward. Un riferimento alla funzione restituito è memorizzato in una costante chiamata moveNearerToZero.

Ora che moveNearerToZero si riferisce alla funzione corretta, può essere utilizzato per contare a zero:

println(“Counting to zero:”)

// Counting to zero:

while currentValue != 0 {
println(“\(currentValue)… “)
currentValue = moveNearerToZero(currentValue)
}
println(“zero!”)
// 3…
// 2…
// 1…
// zero!

Funzioni nidificate
Tutte le funzioni che avete incontrato finora in questo capitolo sono esempi di funzioni globali, quindi definite in un ambito globale. È inoltre possibile definire funzioni all’interno dei corpi di altre funzioni, conosciute come funzioni nidificate.

Le Funzioni nidificate sono nascoste dal mondo esterno per impostazione predefinita, possono quindi essere chiamate e utilizzate solamente all’interno della funzione in cui sono contenute. Una funzione contenitrice può restituire una delle sue funzioni nidificate per consentire ad un’altra funzione di utilizzare la sua funzione nidificata, altrimenti non accessibile dall’esterno:

func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
func stepForward(input: Int) -> Int { return input + 1 }
func stepBackward(input: Int) -> Int { return input – 1 }
return backwards ? stepBackward : stepForward
}
var currentValue = -4
let moveNearerToZero = chooseStepFunction(currentValue > 0)
// moveNearerToZero now refers to the nested stepForward() function
while currentValue != 0 {
println(“\(currentValue)… “)
currentValue = moveNearerToZero(currentValue)
}
println(“zero!”)
// -4…
// -3…
// -2…
// -1…
// zero!

VOLETE ESSERE AGGIORNATI TEMPESTIVAMENTE ALL’USCITA DI UN NUOVO CAPITOLO ? BASTA UN LIKE SULLA NOSTRA PAGINA FACEBOOK!