> For the complete documentation index, see [llms.txt](https://swift.unicorndonkeys.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://swift.unicorndonkeys.com/guida-al-linguaggio/funzioni.md).

# Funzioni (Functions)

Definisci e chiama funzioni, etichettane gli argomenti e usane i valori di ritorno.

Le *funzioni* sono blocchi di codice autonomi che eseguono un compito specifico. Dai a una funzione un nome che identifica ciò che fa, e questo nome viene usato per “chiamare” la funzione affinché esegua il suo compito quando necessario.

La sintassi unificata delle funzioni di Swift è abbastanza flessibile da esprimere qualsiasi cosa, da una semplice funzione in stile C senza nomi di parametri a un complesso metodo in stile Objective-C con nomi ed etichette degli argomenti per ciascun parametro. I parametri possono fornire valori predefiniti per semplificare le chiamate di funzione e possono essere passati come parametri in-out, che modificano una variabile passata una volta che la funzione ha completato la sua esecuzione.

Ogni funzione in Swift ha un tipo, costituito dai tipi dei parametri e dal tipo di ritorno della funzione. Puoi usare questo tipo come qualsiasi altro tipo in Swift, il che rende facile passare funzioni come parametri ad altre funzioni, e restituire funzioni da funzioni. Le funzioni possono anche essere scritte all'interno di altre funzioni per incapsulare funzionalità utili all'interno dell'ambito di una funzione annidata.

## Definire e chiamare funzioni <a href="#definire-e-chiamare-funzioni" id="definire-e-chiamare-funzioni"></a>

Quando definisci una funzione, puoi facoltativamente definire uno o più valori con nome e tipo che la funzione accetta come input, noti come *parametri*. Puoi anche facoltativamente definire un tipo di valore che la funzione restituirà come output quando avrà terminato, noto come il suo *tipo di ritorno*.

Ogni funzione ha un *nome di funzione*, che descrive il compito che la funzione esegue. Per usare una funzione, “chiami” quella funzione con il suo nome e le passi dei valori di input (noti come *argomenti*) che corrispondono ai tipi dei parametri della funzione. Gli argomenti di una funzione devono sempre essere forniti nello stesso ordine dell'elenco dei parametri della funzione.

La funzione nell'esempio seguente si chiama `greet(person:)`, perché è ciò che fa — accetta come input il nome di una persona e restituisce un saluto per quella persona. Per ottenere questo, definisci un parametro di input — un valore `String` chiamato `person` — e un tipo di ritorno `String`, che conterrà un saluto per quella persona:

```swift
func greet(person: String) -> String {
    let greeting = "Hello, " + person + "!"
    return greeting
}
```

Tutte queste informazioni sono raccolte nella *definizione* della funzione, che è preceduta dalla parola chiave `func`. Indichi il tipo di ritorno della funzione con la *freccia di ritorno* `->` (un trattino seguito da una parentesi angolare chiusa), seguita dal nome del tipo da restituire.

La definizione descrive che cosa fa la funzione, che cosa si aspetta di ricevere, e che cosa restituisce quando ha terminato. La definizione rende facile chiamare la funzione in modo non ambiguo da altri punti del tuo codice:

```swift
print(greet(person: "Anna"))
// Stampa "Hello, Anna!"
print(greet(person: "Brian"))
// Stampa "Hello, Brian!"
```

Chiami la funzione `greet(person:)` passandole un valore `String` dopo l'etichetta dell'argomento `person`, come in `greet(person: "Anna")`. Poiché la funzione restituisce un valore `String`, `greet(person:)` può essere racchiusa in una chiamata alla funzione `print(_:separator:terminator:)` per stampare quella stringa e vederne il valore di ritorno, come mostrato sopra.

{% hint style="info" %}
**Nota:** La funzione `print(_:separator:terminator:)` non ha un'etichetta per il suo primo argomento, e i suoi altri argomenti sono opzionali perché hanno un valore predefinito. Queste varianti della sintassi delle funzioni sono discusse più avanti in [Etichette degli argomenti e nomi dei parametri delle funzioni](/guida-al-linguaggio/funzioni.md#etichette-degli-argomenti-e-nomi-dei-parametri-delle-funzioni) e in [Valori predefiniti dei parametri](/guida-al-linguaggio/funzioni.md#valori-predefiniti-dei-parametri).
{% endhint %}

Il corpo della funzione `greet(person:)` inizia definendo una nuova costante `String` chiamata `greeting` e impostandola a un semplice messaggio di saluto. Questo saluto viene poi restituito all'esterno della funzione usando la parola chiave `return`. Nella riga di codice che dice `return greeting`, la funzione termina la sua esecuzione e restituisce il valore corrente di `greeting`.

Puoi chiamare la funzione `greet(person:)` più volte con valori di input diversi. L'esempio qui sopra mostra che cosa succede se viene chiamata con un valore di input `"Anna"` e con un valore di input `"Brian"`. La funzione restituisce un saluto su misura in ciascun caso.

Per rendere più breve il corpo di questa funzione, puoi combinare la creazione del messaggio e l'istruzione return in un'unica riga:

```swift
func greetAgain(person: String) -> String {
    return "Hello again, " + person + "!"
}
print(greetAgain(person: "Anna"))
// Stampa "Hello again, Anna!"
```

## Parametri e valori di ritorno delle funzioni <a href="#parametri-e-valori-di-ritorno-delle-funzioni" id="parametri-e-valori-di-ritorno-delle-funzioni"></a>

In Swift i parametri e i valori di ritorno delle funzioni sono estremamente flessibili. Puoi definire qualsiasi cosa, da una semplice funzione di utilità con un unico parametro senza nome a una funzione complessa con nomi di parametri espressivi e diverse opzioni per i parametri.

### Funzioni senza parametri <a href="#funzioni-senza-parametri" id="funzioni-senza-parametri"></a>

Le funzioni non sono obbligate a definire parametri di input. Ecco una funzione senza parametri di input, che restituisce sempre lo stesso messaggio `String` ogni volta che viene chiamata:

```swift
func sayHelloWorld() -> String {
    return "hello, world"
}
print(sayHelloWorld())
// Stampa "hello, world".
```

La definizione della funzione richiede comunque le parentesi dopo il nome della funzione, anche se non accetta alcun parametro. Anche quando la funzione viene chiamata, il suo nome è seguito da una coppia di parentesi vuote.

### Funzioni con più parametri <a href="#funzioni-con-piu-parametri" id="funzioni-con-piu-parametri"></a>

Le funzioni possono avere più parametri di input, che vengono scritti all'interno delle parentesi della funzione, separati da virgole.

Questa funzione accetta come input il nome di una persona e l'indicazione se sia già stata salutata, e restituisce un saluto appropriato per quella persona:

```swift
func greet(person: String, alreadyGreeted: Bool) -> String {
    if alreadyGreeted {
        return greetAgain(person: person)
    } else {
        return greet(person: person)
    }
}
print(greet(person: "Tim", alreadyGreeted: true))
// Stampa "Hello again, Tim!"
```

Chiami la funzione `greet(person:alreadyGreeted:)` passandole sia un valore di argomento `String` etichettato `person` sia un valore di argomento `Bool` etichettato `alreadyGreeted` tra parentesi, separati da virgole. Nota che questa funzione è distinta dalla funzione `greet(person:)` mostrata in una sezione precedente. Sebbene entrambe le funzioni abbiano nomi che iniziano con `greet`, la funzione `greet(person:alreadyGreeted:)` accetta due argomenti mentre la funzione `greet(person:)` ne accetta uno solo.

### Funzioni senza valori di ritorno <a href="#funzioni-senza-valori-di-ritorno" id="funzioni-senza-valori-di-ritorno"></a>

Le funzioni non sono obbligate a definire un tipo di ritorno. Ecco una versione della funzione `greet(person:)`, che stampa il proprio valore `String` invece di restituirlo:

```swift
func greet(person: String) {
    print("Hello, \(person)!")
}
greet(person: "Dave")
// Stampa "Hello, Dave!"
```

Poiché non ha bisogno di restituire un valore, la definizione della funzione non include la freccia di ritorno (`->`) né un tipo di ritorno.

{% hint style="info" %}
**Nota:** A rigor di termini, questa versione della funzione `greet(person:)` restituisce *comunque* un valore, anche se non è definito alcun valore di ritorno. Le funzioni senza un tipo di ritorno definito restituiscono un valore speciale di tipo `Void`. Si tratta semplicemente di una tupla vuota, che si scrive `()`.
{% endhint %}

Il valore di ritorno di una funzione può essere ignorato quando la si chiama:

```swift
func printAndCount(string: String) -> Int {
    print(string)
    return string.count
}
func printWithoutCounting(string: String) {
    let _ = printAndCount(string: string)
}
printAndCount(string: "hello, world")
// stampa "hello, world" e restituisce un valore di 12
printWithoutCounting(string: "hello, world")
// stampa "hello, world" ma non restituisce un valore
```

La prima funzione, `printAndCount(string:)`, stampa una stringa, e poi restituisce il suo numero di caratteri come `Int`. La seconda funzione, `printWithoutCounting(string:)`, chiama la prima funzione, ma ne ignora il valore di ritorno. Quando viene chiamata la seconda funzione, il messaggio viene comunque stampato dalla prima funzione, ma il valore restituito non viene usato.

{% hint style="info" %}
**Nota:** I valori di ritorno possono essere ignorati, ma una funzione che dichiara di restituire un valore deve sempre farlo. Una funzione con un tipo di ritorno definito non può permettere al controllo di uscire dal fondo della funzione senza restituire un valore, e tentare di farlo produrrà un errore in fase di compilazione.
{% endhint %}

### Funzioni con più valori di ritorno <a href="#funzioni-con-piu-valori-di-ritorno" id="funzioni-con-piu-valori-di-ritorno"></a>

Puoi usare un tipo tupla come tipo di ritorno di una funzione per restituire più valori come parte di un unico valore di ritorno composto.

L'esempio seguente definisce una funzione chiamata `minMax(array:)`, che trova il numero più piccolo e quello più grande in un array di valori `Int`:

```swift
func minMax(array: [Int]) -> (min: Int, max: Int) {
    var currentMin = array[0]
    var currentMax = array[0]
    for value in array[1..<array.count] {
        if value < currentMin {
            currentMin = value
        } else if value > currentMax {
            currentMax = value
        }
    }
    return (currentMin, currentMax)
}
```

La funzione `minMax(array:)` restituisce una tupla contenente due valori `Int`. Questi valori sono etichettati `min` e `max` in modo che vi si possa accedere per nome quando si interroga il valore di ritorno della funzione.

Il corpo della funzione `minMax(array:)` inizia impostando due variabili di lavoro chiamate `currentMin` e `currentMax` al valore del primo intero dell'array. La funzione itera poi sui valori rimanenti dell'array e controlla ciascun valore per vedere se è rispettivamente più piccolo o più grande dei valori di `currentMin` e `currentMax`. Infine, i valori minimo e massimo complessivi vengono restituiti come una tupla di due valori `Int`.

Poiché i valori membro della tupla sono denominati come parte del tipo di ritorno della funzione, vi si può accedere con la sintassi a punto per recuperare i valori minimo e massimo trovati:

```swift
let bounds = minMax(array: [8, -6, 2, 109, 3, 71])
print("min is \(bounds.min) and max is \(bounds.max)")
// Stampa "min is -6 and max is 109".
```

Nota che i membri della tupla non devono essere denominati nel punto in cui la tupla viene restituita dalla funzione, perché i loro nomi sono già specificati come parte del tipo di ritorno della funzione.

#### Tipi di ritorno tupla opzionali <a href="#tipi-di-ritorno-tupla-opzionali" id="tipi-di-ritorno-tupla-opzionali"></a>

Se il tipo tupla da restituire da una funzione può potenzialmente avere “nessun valore” per l'intera tupla, puoi usare un tipo di ritorno tupla *opzionale* per riflettere il fatto che l'intera tupla può essere `nil`. Scrivi un tipo di ritorno tupla opzionale collocando un punto interrogativo dopo la parentesi di chiusura del tipo tupla, come in `(Int, Int)?` o `(String, Int, Bool)?`.

{% hint style="info" %}
**Nota:** Un tipo tupla opzionale come `(Int, Int)?` è diverso da una tupla che contiene tipi opzionali come `(Int?, Int?)`. Con un tipo tupla opzionale, è opzionale l'intera tupla, non solo ciascun singolo valore al suo interno.
{% endhint %}

La funzione `minMax(array:)` qui sopra restituisce una tupla contenente due valori `Int`. Tuttavia, la funzione non esegue alcun controllo di sicurezza sull'array che le viene passato. Se l'argomento `array` contiene un array vuoto, la funzione `minMax(array:)`, come definita sopra, attiverà un errore in fase di esecuzione quando tenterà di accedere a `array[0]`.

Per gestire in modo sicuro un array vuoto, scrivi la funzione `minMax(array:)` con un tipo di ritorno tupla opzionale e restituisci un valore `nil` quando l'array è vuoto:

```swift
func minMax(array: [Int]) -> (min: Int, max: Int)? {
    if array.isEmpty { return nil }
    var currentMin = array[0]
    var currentMax = array[0]
    for value in array[1..<array.count] {
        if value < currentMin {
            currentMin = value
        } else if value > currentMax {
            currentMax = value
        }
    }
    return (currentMin, currentMax)
}
```

Puoi usare l'optional binding per verificare se questa versione della funzione `minMax(array:)` restituisce un effettivo valore tupla oppure `nil`:

```swift
if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) {
    print("min is \(bounds.min) and max is \(bounds.max)")
}
// Stampa "min is -6 and max is 109".
```

### Funzioni con un return implicito <a href="#funzioni-con-un-return-implicito" id="funzioni-con-un-return-implicito"></a>

Se l'intero corpo della funzione è una singola espressione, la funzione restituisce implicitamente quell'espressione. Per esempio, le due funzioni seguenti hanno lo stesso comportamento:

```swift
func greeting(for person: String) -> String {
    "Hello, " + person + "!"
}
print(greeting(for: "Dave"))
// Stampa "Hello, Dave!"

func anotherGreeting(for person: String) -> String {
    return "Hello, " + person + "!"
}
print(anotherGreeting(for: "Dave"))
// Stampa "Hello, Dave!"
```

L'intera definizione della funzione `greeting(for:)` è il messaggio di saluto che restituisce, il che significa che può usare questa forma più breve. La funzione `anotherGreeting(for:)` restituisce lo stesso messaggio di saluto, usando la parola chiave `return` come una funzione più lunga. Qualsiasi funzione che scrivi come una sola riga `return` può omettere il `return`.

Come vedrai in [Dichiarazione abbreviata del getter](/guida-al-linguaggio/proprieta.md#dichiarazione-abbreviata-del-getter), anche i getter delle proprietà possono usare un return implicito.

{% hint style="info" %}
**Nota:** Il codice che scrivi come valore di ritorno implicito deve restituire un qualche valore. Per esempio, non puoi usare `print(13)` come valore di ritorno implicito. Tuttavia, puoi usare una funzione che non restituisce mai, come `fatalError("Oh no!")`, come valore di ritorno implicito, perché Swift sa che il return implicito non avviene.
{% endhint %}

## Etichette degli argomenti e nomi dei parametri delle funzioni <a href="#etichette-degli-argomenti-e-nomi-dei-parametri-delle-funzioni" id="etichette-degli-argomenti-e-nomi-dei-parametri-delle-funzioni"></a>

Ogni parametro di una funzione ha sia un'*etichetta dell'argomento* sia un *nome del parametro*. L'etichetta dell'argomento viene usata quando si chiama la funzione; ogni argomento viene scritto nella chiamata di funzione preceduto dalla sua etichetta dell'argomento. Il nome del parametro viene usato nell'implementazione della funzione. Per impostazione predefinita, i parametri usano il loro nome del parametro come etichetta dell'argomento.

```swift
func someFunction(firstParameterName: Int, secondParameterName: Int) {
    // Nel corpo della funzione, firstParameterName e secondParameterName
    // si riferiscono ai valori degli argomenti per il primo e il secondo parametro.
}
someFunction(firstParameterName: 1, secondParameterName: 2)
```

Tutti i parametri devono avere nomi univoci. Sebbene sia possibile che più parametri abbiano la stessa etichetta dell'argomento, etichette degli argomenti univoche aiutano a rendere il tuo codice più leggibile.

### Specificare le etichette degli argomenti <a href="#specificare-le-etichette-degli-argomenti" id="specificare-le-etichette-degli-argomenti"></a>

Scrivi un'etichetta dell'argomento prima del nome del parametro, separati da uno spazio:

```swift
func someFunction(argumentLabel parameterName: Int) {
    // Nel corpo della funzione, parameterName si riferisce al valore dell'argomento
    // per quel parametro.
}
```

Ecco una variante della funzione `greet(person:)` che accetta il nome e la città natale di una persona e restituisce un saluto:

```swift
func greet(person: String, from hometown: String) -> String {
    return "Hello \(person)!  Glad you could visit from \(hometown)."
}
print(greet(person: "Bill", from: "Cupertino"))
// Stampa "Hello Bill!  Glad you could visit from Cupertino."
```

L'uso delle etichette degli argomenti può permettere di chiamare una funzione in modo espressivo, simile a una frase, pur fornendo un corpo della funzione leggibile e chiaro nelle intenzioni.

### Omettere le etichette degli argomenti <a href="#omettere-le-etichette-degli-argomenti" id="omettere-le-etichette-degli-argomenti"></a>

Se non vuoi un'etichetta dell'argomento per un parametro, scrivi un trattino basso (`_`) invece di un'etichetta esplicita per quel parametro.

```swift
func someFunction(_ firstParameterName: Int, secondParameterName: Int) {
    // Nel corpo della funzione, firstParameterName e secondParameterName
    // si riferiscono ai valori degli argomenti per il primo e il secondo parametro.
}
someFunction(1, secondParameterName: 2)
```

Se un parametro ha un'etichetta dell'argomento, l'argomento *deve* essere etichettato quando chiami la funzione.

### Valori predefiniti dei parametri <a href="#valori-predefiniti-dei-parametri" id="valori-predefiniti-dei-parametri"></a>

Puoi definire un *valore predefinito* per qualsiasi parametro di una funzione assegnando un valore al parametro dopo il tipo di quel parametro. Se è definito un valore predefinito, puoi omettere quel parametro quando chiami la funzione.

```swift
func someFunction(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) {
    // Se ometti il secondo argomento quando chiami questa funzione, allora
    // il valore di parameterWithDefault è 12 all'interno del corpo della funzione.
}
someFunction(parameterWithoutDefault: 3, parameterWithDefault: 6) // parameterWithDefault vale 6
someFunction(parameterWithoutDefault: 4) // parameterWithDefault vale 12
```

Colloca i parametri che non hanno valori predefiniti all'inizio dell'elenco dei parametri di una funzione, prima dei parametri che hanno valori predefiniti. I parametri che non hanno valori predefiniti sono di solito più importanti per il significato della funzione — scriverli per primi rende più facile riconoscere che si sta chiamando la stessa funzione, indipendentemente dal fatto che vengano omessi dei parametri predefiniti.

### Parametri variadici <a href="#parametri-variadici" id="parametri-variadici"></a>

Un *parametro variadico* accetta zero o più valori di un tipo specificato. Usi un parametro variadico per specificare che al parametro può essere passato un numero variabile di valori di input quando la funzione viene chiamata. Scrivi i parametri variadici inserendo tre caratteri punto (`...`) dopo il nome del tipo del parametro.

I valori passati a un parametro variadico sono resi disponibili all'interno del corpo della funzione come un array del tipo appropriato. Per esempio, un parametro variadico con nome `numbers` e tipo `Double...` è reso disponibile all'interno del corpo della funzione come un array costante chiamato `numbers` di tipo `[Double]`.

L'esempio seguente calcola la *media aritmetica* (nota anche semplicemente come *media*) di un elenco di numeri di qualsiasi lunghezza:

```swift
func arithmeticMean(_ numbers: Double...) -> Double {
    var total: Double = 0
    for number in numbers {
        total += number
    }
    return total / Double(numbers.count)
}
arithmeticMean(1, 2, 3, 4, 5)
// restituisce 3.0, che è la media aritmetica di questi cinque numeri
arithmeticMean(3, 8.25, 18.75)
// restituisce 10.0, che è la media aritmetica di questi tre numeri
```

Una funzione può avere più parametri variadici. Il primo parametro che segue un parametro variadico deve avere un'etichetta dell'argomento. L'etichetta dell'argomento rende non ambiguo quali argomenti vengono passati al parametro variadico e quali argomenti vengono passati ai parametri che seguono il parametro variadico.

### Parametri in-out <a href="#parametri-in-out" id="parametri-in-out"></a>

I parametri delle funzioni sono costanti per impostazione predefinita. Tentare di modificare il valore di un parametro di una funzione dall'interno del corpo di quella funzione produce un errore in fase di compilazione. Ciò significa che non puoi modificare per errore il valore di un parametro. Se vuoi che una funzione modifichi il valore di un parametro, e vuoi che quelle modifiche persistano dopo che la chiamata di funzione è terminata, definisci invece quel parametro come *parametro in-out*.

Scrivi un parametro in-out collocando la parola chiave `inout` subito prima del tipo di un parametro. Un parametro in-out ha un valore che viene passato *dentro* la funzione, viene modificato dalla funzione, e viene restituito *fuori* dalla funzione per sostituire il valore originale. Per una discussione dettagliata del comportamento dei parametri in-out e delle relative ottimizzazioni del compilatore, vedi [Parametri in-out](/riferimento-del-linguaggio/dichiarazioni.md#parametri-in-out).

Puoi passare solo una variabile come argomento di un parametro in-out. Non puoi passare una costante o un valore letterale come argomento, perché costanti e letterali non possono essere modificati. Collochi una e commerciale (`&`) direttamente prima del nome di una variabile quando la passi come argomento a un parametro in-out, per indicare che può essere modificata dalla funzione.

{% hint style="info" %}
**Nota:** I parametri in-out non possono avere valori predefiniti, e i parametri variadici non possono essere contrassegnati come `inout`.
{% endhint %}

Ecco un esempio di una funzione chiamata `swapTwoInts(_:_:)`, che ha due parametri interi in-out chiamati `a` e `b`:

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

La funzione `swapTwoInts(_:_:)` si limita a scambiare il valore di `b` in `a`, e il valore di `a` in `b`. La funzione esegue questo scambio memorizzando il valore di `a` in una costante temporanea chiamata `temporaryA`, assegnando il valore di `b` ad `a`, e poi assegnando `temporaryA` a `b`.

Puoi chiamare la funzione `swapTwoInts(_:_:)` con due variabili di tipo `Int` per scambiarne i valori. Nota che ai nomi di `someInt` e `anotherInt` viene anteposta una e commerciale quando vengono passati alla funzione `swapTwoInts(_:_:)`:

```swift
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
// Stampa "someInt is now 107, and anotherInt is now 3".
```

L'esempio qui sopra mostra che i valori originali di `someInt` e `anotherInt` vengono modificati dalla funzione `swapTwoInts(_:_:)`, anche se sono stati originariamente definiti al di fuori della funzione.

{% hint style="info" %}
**Nota:** I parametri in-out non sono la stessa cosa della restituzione di un valore da una funzione. L'esempio `swapTwoInts` qui sopra non definisce un tipo di ritorno né restituisce un valore, ma modifica comunque i valori di `someInt` e `anotherInt`. I parametri in-out sono un modo alternativo con cui una funzione può avere un effetto al di fuori dell'ambito del corpo della funzione.
{% endhint %}

## Tipi funzione <a href="#tipi-funzione" id="tipi-funzione"></a>

Ogni funzione ha uno specifico *tipo funzione*, costituito dai tipi dei parametri e dal tipo di ritorno della funzione.

Per esempio:

```swift
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 accettano ciascuna due valori `Int`, e restituiscono un valore `Int`, che è il risultato dell'esecuzione di un'operazione matematica appropriata.

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

“Una funzione che ha due parametri, entrambi di tipo `Int`, e che restituisce un valore di tipo `Int`.”

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

```swift
func printHelloWorld() {
    print("hello, world")
}
```

Il tipo di questa funzione è `() -> Void`, ovvero “una funzione che non ha parametri, e restituisce `Void`.”

### Usare i tipi funzione <a href="#usare-i-tipi-funzione" id="usare-i-tipi-funzione"></a>

Usi i tipi funzione proprio come qualsiasi altro tipo in Swift. Per esempio, puoi definire una costante o una variabile di un tipo funzione e assegnare una funzione appropriata a quella variabile:

```swift
var mathFunction: (Int, Int) -> Int = addTwoInts
```

Questo può essere letto come:

“Definisci una variabile chiamata `mathFunction`, che ha il tipo ‘una funzione che accetta due valori `Int`, e restituisce un valore `Int`.’ Imposta questa nuova variabile in modo che faccia riferimento alla funzione chiamata `addTwoInts`.”

La funzione `addTwoInts(_:_:)` ha lo stesso tipo della variabile `mathFunction`, e quindi questo assegnamento è consentito dal controllore dei tipi di Swift.

Ora puoi chiamare la funzione assegnata con il nome `mathFunction`:

```swift
print("Result: \(mathFunction(2, 3))")
// Stampa "Result: 5".
```

Una funzione diversa con lo stesso tipo corrispondente può essere assegnata alla stessa variabile, nello stesso modo dei tipi non funzione:

```swift
mathFunction = multiplyTwoInts
print("Result: \(mathFunction(2, 3))")
// Stampa "Result: 6".
```

Come per qualsiasi altro tipo, puoi lasciare che sia Swift a inferire il tipo funzione quando assegni una funzione a una costante o a una variabile:

```swift
let anotherMathFunction = addTwoInts
// anotherMathFunction viene inferita come di tipo (Int, Int) -> Int
```

### Tipi funzione come tipi dei parametri <a href="#tipi-funzione-come-tipi-dei-parametri" id="tipi-funzione-come-tipi-dei-parametri"></a>

Puoi usare un tipo funzione come `(Int, Int) -> Int` come tipo di un parametro di un'altra funzione. Questo ti permette di lasciare che alcuni aspetti dell'implementazione di una funzione siano forniti da chi chiama la funzione, al momento della chiamata.

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

```swift
func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
    print("Result: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5)
// Stampa "Result: 8".
```

Questo esempio definisce una funzione chiamata `printMathResult(_:_:_:)`, che ha tre parametri. Il primo parametro si chiama `mathFunction`, ed è di tipo `(Int, Int) -> Int`. Puoi passare qualsiasi funzione di quel tipo come argomento per questo primo parametro. Il secondo e il terzo parametro si chiamano `a` e `b`, e sono entrambi di tipo `Int`. Questi vengono usati come i due valori di input per la funzione matematica fornita.

Quando viene chiamata `printMathResult(_:_:_:)`, le vengono passati la funzione `addTwoInts(_:_:)` e i valori interi `3` e `5`. Essa chiama la funzione fornita con i valori `3` e `5`, e stampa il risultato `8`.

Il ruolo di `printMathResult(_:_:_:)` è stampare il risultato di una chiamata a una funzione matematica di un tipo appropriato. Non importa che cosa faccia effettivamente l'implementazione di quella funzione — importa solo che la funzione sia del tipo corretto. Questo permette a `printMathResult(_:_:_:)` di delegare parte della sua funzionalità a chi chiama la funzione in modo sicuro rispetto ai tipi.

### Tipi funzione come tipi di ritorno <a href="#tipi-funzione-come-tipi-di-ritorno" id="tipi-funzione-come-tipi-di-ritorno"></a>

Puoi usare un tipo funzione come tipo di ritorno di un'altra funzione. Lo fai scrivendo un tipo funzione completo subito dopo la freccia di ritorno (`->`) della funzione che lo restituisce.

L'esempio successivo definisce due semplici funzioni chiamate `stepForward(_:)` e `stepBackward(_:)`. La funzione `stepForward(_:)` restituisce un valore superiore di uno al suo valore di input, e la funzione `stepBackward(_:)` restituisce un valore inferiore di uno al suo valore di input. Entrambe le funzioni hanno tipo `(Int) -> Int`:

```swift
func stepForward(_ input: Int) -> Int {
    return input + 1
}
func stepBackward(_ input: Int) -> Int {
    return input - 1
}
```

Ecco una funzione chiamata `chooseStepFunction(backward:)`, il cui tipo di ritorno è `(Int) -> Int`. La funzione `chooseStepFunction(backward:)` restituisce la funzione `stepForward(_:)` o la funzione `stepBackward(_:)` in base a un parametro booleano chiamato `backward`:

```swift
func chooseStepFunction(backward: Bool) -> (Int) -> Int {
    return backward ? stepBackward : stepForward
}
```

Ora puoi usare `chooseStepFunction(backward:)` per ottenere una funzione che avanzerà in una direzione o nell'altra:

```swift
var currentValue = 3
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero ora si riferisce alla funzione stepBackward()
```

L'esempio qui sopra determina se è necessario un passo positivo o negativo per avvicinare progressivamente a zero una variabile chiamata `currentValue`. `currentValue` ha un valore iniziale di `3`, il che significa che `currentValue > 0` restituisce `true`, facendo sì che `chooseStepFunction(backward:)` restituisca la funzione `stepBackward(_:)`. Un riferimento alla funzione restituita viene memorizzato in una costante chiamata `moveNearerToZero`.

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

```swift
print("Counting to zero:")
// Counting to zero:
while currentValue != 0 {
    print("\(currentValue)... ")
    currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// 3...
// 2...
// 1...
// zero!
```

## Funzioni annidate <a href="#funzioni-annidate" id="funzioni-annidate"></a>

Tutte le funzioni che hai incontrato finora in questo capitolo sono state esempi di *funzioni globali*, definite in un ambito globale. Puoi anche definire funzioni all'interno dei corpi di altre funzioni, note come *funzioni annidate*.

Le funzioni annidate sono nascoste al mondo esterno per impostazione predefinita, ma possono comunque essere chiamate e usate dalla funzione che le racchiude. Una funzione che le racchiude può anche restituire una delle sue funzioni annidate per permettere che la funzione annidata venga usata in un altro ambito.

Puoi riscrivere l'esempio `chooseStepFunction(backward:)` visto sopra per usare e restituire funzioni annidate:

```swift
func chooseStepFunction(backward: Bool) -> (Int) -> Int {
    func stepForward(input: Int) -> Int { return input + 1 }
    func stepBackward(input: Int) -> Int { return input - 1 }
    return backward ? stepBackward : stepForward
}
var currentValue = -4
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero ora si riferisce alla funzione annidata stepForward()
while currentValue != 0 {
    print("\(currentValue)... ")
    currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// -4...
// -3...
// -2...
// -1...
// zero!
```
