> 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/closure.md).

# Closure (Closures)

Raggruppa codice che viene eseguito insieme, senza creare una funzione con nome.

Le *closure* sono blocchi di funzionalità autonomi che possono essere passati da una parte all'altra e usati nel tuo codice. Le closure in Swift sono simili a closure, funzioni anonime, lambda e blocchi di altri linguaggi di programmazione.

Le closure possono catturare e memorizzare riferimenti a qualsiasi costante e variabile del contesto in cui sono definite. Questo è noto come *chiusura* (closing over) su quelle costanti e variabili. Swift gestisce per te tutta la gestione della memoria relativa alla cattura.

{% hint style="info" %}
**Nota:** Non preoccuparti se non conosci il concetto di cattura. È spiegato in dettaglio più avanti in [Catturare valori](/guida-al-linguaggio/closure.md#catturare-valori).
{% endhint %}

Le funzioni globali e annidate, come presentate in [Funzioni](/guida-al-linguaggio/funzioni.md), sono in realtà casi particolari di closure. Le closure assumono una di tre forme:

* Le funzioni globali sono closure che hanno un nome e non catturano alcun valore.
* Le funzioni annidate sono closure che hanno un nome e possono catturare valori dalla funzione che le racchiude.
* Le espressioni closure sono closure senza nome scritte con una sintassi leggera che possono catturare valori dal contesto circostante.

Le espressioni closure di Swift hanno uno stile pulito e chiaro, con ottimizzazioni che favoriscono una sintassi breve e ordinata negli scenari comuni. Queste ottimizzazioni comprendono:

* L'inferenza dei tipi dei parametri e del valore di ritorno dal contesto
* I return impliciti nelle closure a singola espressione
* I nomi abbreviati degli argomenti
* La sintassi delle trailing closure

## Espressioni closure <a href="#espressioni-closure" id="espressioni-closure"></a>

Le funzioni annidate, come presentate in [Funzioni annidate](/guida-al-linguaggio/funzioni.md#funzioni-annidate), sono un mezzo comodo per denominare e definire blocchi di codice autonomi come parte di una funzione più grande. Tuttavia, a volte è utile scrivere versioni più brevi di costrutti simili a funzioni senza una dichiarazione e un nome completi. Questo è particolarmente vero quando lavori con funzioni o metodi che accettano funzioni come uno o più dei loro argomenti.

Le *espressioni closure* sono un modo per scrivere closure inline con una sintassi breve e mirata. Le espressioni closure forniscono diverse ottimizzazioni sintattiche per scrivere closure in forma abbreviata senza perdita di chiarezza o di intenzione. Gli esempi di espressioni closure seguenti illustrano queste ottimizzazioni perfezionando un unico esempio del metodo `sorted(by:)` attraverso diverse iterazioni, ognuna delle quali esprime la stessa funzionalità in modo più sintetico.

### Il metodo sorted <a href="#il-metodo-sorted" id="il-metodo-sorted"></a>

La libreria standard di Swift fornisce un metodo chiamato `sorted(by:)`, che ordina un array di valori di un tipo noto, in base all'output di una closure di ordinamento che fornisci tu. Una volta completato il processo di ordinamento, il metodo `sorted(by:)` restituisce un nuovo array dello stesso tipo e della stessa dimensione di quello vecchio, con i suoi elementi nel corretto ordine. L'array originale non viene modificato dal metodo `sorted(by:)`.

Gli esempi di espressioni closure seguenti usano il metodo `sorted(by:)` per ordinare un array di valori `String` in ordine alfabetico inverso. Ecco l'array iniziale da ordinare:

```swift
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
```

Il metodo `sorted(by:)` accetta una closure che prende due argomenti dello stesso tipo del contenuto dell'array, e restituisce un valore `Bool` per dire se il primo valore deve comparire prima o dopo il secondo valore una volta ordinati i valori. La closure di ordinamento deve restituire `true` se il primo valore deve comparire *prima* del secondo valore, e `false` in caso contrario.

Questo esempio ordina un array di valori `String`, e quindi la closure di ordinamento deve essere una funzione di tipo `(String, String) -> Bool`.

Un modo per fornire la closure di ordinamento è scrivere una normale funzione del tipo corretto, e passarla come argomento al metodo `sorted(by:)`:

```swift
func backward(_ s1: String, _ s2: String) -> Bool {
    return s1 > s2
}
var reversedNames = names.sorted(by: backward)
// reversedNames è uguale a ["Ewa", "Daniella", "Chris", "Barry", "Alex"]
```

Se la prima stringa (`s1`) è maggiore della seconda stringa (`s2`), la funzione `backward(_:_:)` restituirà `true`, indicando che `s1` deve comparire prima di `s2` nell'array ordinato. Per i caratteri nelle stringhe, “maggiore di” significa “compare più avanti nell'alfabeto di”. Ciò significa che la lettera `"B"` è “maggiore” della lettera `"A"`, e la stringa `"Tom"` è maggiore della stringa `"Tim"`. Questo produce un ordinamento alfabetico inverso, con `"Barry"` collocato prima di `"Alex"`, e così via.

Tuttavia, questo è un modo piuttosto prolisso di scrivere quella che è essenzialmente una funzione a singola espressione (`a > b`). In questo esempio, sarebbe preferibile scrivere la closure di ordinamento inline, usando la sintassi delle espressioni closure.

### Sintassi delle espressioni closure <a href="#sintassi-delle-espressioni-closure" id="sintassi-delle-espressioni-closure"></a>

La sintassi delle espressioni closure ha la seguente forma generale:

```swift
{ (<#parameters#>) -> <#return type#> in
   <#statements#>
}
```

I *parameters* (parametri) nella sintassi delle espressioni closure possono essere parametri in-out, ma non possono avere un valore predefinito. I parametri variadici possono essere usati se assegni un nome al parametro variadico. Anche le tuple possono essere usate come tipi dei parametri e tipi di ritorno.

L'esempio seguente mostra una versione in forma di espressione closure della funzione `backward(_:_:)` vista sopra:

```swift
reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
    return s1 > s2
})
```

Nota che la dichiarazione dei parametri e del tipo di ritorno di questa closure inline è identica alla dichiarazione della funzione `backward(_:_:)`. In entrambi i casi, si scrive `(s1: String, s2: String) -> Bool`. Tuttavia, per l'espressione closure inline, i parametri e il tipo di ritorno sono scritti *dentro* le parentesi graffe, non al di fuori di esse.

L'inizio del corpo della closure è introdotto dalla parola chiave `in`. Questa parola chiave indica che la definizione dei parametri e del tipo di ritorno della closure è terminata, e che il corpo della closure sta per iniziare.

Poiché il corpo della closure è così breve, può persino essere scritto su un'unica riga:

```swift
reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2 } )
```

Questo illustra che la chiamata complessiva al metodo `sorted(by:)` è rimasta la stessa. Una coppia di parentesi racchiude ancora l'intero argomento del metodo. Tuttavia, quell'argomento è ora una closure inline.

### Inferire il tipo dal contesto <a href="#inferire-il-tipo-dal-contesto" id="inferire-il-tipo-dal-contesto"></a>

Poiché la closure di ordinamento viene passata come argomento a un metodo, Swift può inferire i tipi dei suoi parametri e il tipo del valore che restituisce. Il metodo `sorted(by:)` viene chiamato su un array di stringhe, quindi il suo argomento deve essere una funzione di tipo `(String, String) -> Bool`. Ciò significa che i tipi `(String, String)` e `Bool` non devono essere scritti come parte della definizione dell'espressione closure. Poiché tutti i tipi possono essere inferiti, anche la freccia di ritorno (`->`) e le parentesi attorno ai nomi dei parametri possono essere omesse:

```swift
reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } )
```

È sempre possibile inferire i tipi dei parametri e il tipo di ritorno quando si passa una closure a una funzione o a un metodo come espressione closure inline. Di conseguenza, non hai mai bisogno di scrivere una closure inline nella sua forma più completa quando la closure viene usata come argomento di una funzione o di un metodo.

Ciononostante, puoi comunque rendere espliciti i tipi se lo desideri, e farlo è incoraggiato se evita ambiguità per chi legge il tuo codice. Nel caso del metodo `sorted(by:)`, lo scopo della closure è chiaro dal fatto che si sta effettuando un ordinamento, ed è sicuro per un lettore presumere che la closure lavori probabilmente con valori `String`, perché sta contribuendo all'ordinamento di un array di stringhe.

### Return impliciti nelle closure a singola espressione <a href="#return-impliciti-nelle-closure-a-singola-espressione" id="return-impliciti-nelle-closure-a-singola-espressione"></a>

Le closure a singola espressione possono restituire implicitamente il risultato della loro unica espressione omettendo la parola chiave `return` dalla loro dichiarazione, come in questa versione dell'esempio precedente:

```swift
reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )
```

Qui, il tipo funzione dell'argomento del metodo `sorted(by:)` rende chiaro che la closure deve restituire un valore `Bool`. Poiché il corpo della closure contiene una singola espressione (`s1 > s2`) che restituisce un valore `Bool`, non c'è ambiguità, e la parola chiave `return` può essere omessa.

### Nomi abbreviati degli argomenti <a href="#nomi-abbreviati-degli-argomenti" id="nomi-abbreviati-degli-argomenti"></a>

Swift fornisce automaticamente alle closure inline dei nomi abbreviati per gli argomenti, che possono essere usati per riferirsi ai valori degli argomenti della closure con i nomi `$0`, `$1`, `$2` e così via.

Se usi questi nomi abbreviati degli argomenti all'interno della tua espressione closure, puoi omettere l'elenco degli argomenti della closure dalla sua definizione. Il tipo dei nomi abbreviati degli argomenti viene inferito dal tipo funzione atteso, e l'argomento abbreviato con il numero più alto che usi determina il numero di argomenti che la closure accetta. Anche la parola chiave `in` può essere omessa, perché l'espressione closure è costituita interamente dal suo corpo:

```swift
reversedNames = names.sorted(by: { $0 > $1 } )
```

Qui, `$0` e `$1` si riferiscono al primo e al secondo argomento `String` della closure. Poiché `$1` è l'argomento abbreviato con il numero più alto, si considera che la closure accetti due argomenti. Poiché qui la funzione `sorted(by:)` si aspetta una closure i cui argomenti siano entrambi stringhe, gli argomenti abbreviati `$0` e `$1` sono entrambi di tipo `String`.

### Metodi operatore <a href="#metodi-operatore" id="metodi-operatore"></a>

In realtà esiste un modo ancora *più breve* per scrivere l'espressione closure qui sopra. Il tipo `String` di Swift definisce la sua implementazione specifica per le stringhe dell'operatore maggiore di (`>`) come un metodo che ha due parametri di tipo `String`, e restituisce un valore di tipo `Bool`. Questo corrisponde esattamente al tipo di metodo richiesto dal metodo `sorted(by:)`. Pertanto, puoi semplicemente passare l'operatore maggiore di, e Swift inferirà che vuoi usare la sua implementazione specifica per le stringhe:

```swift
reversedNames = names.sorted(by: >)
```

Per saperne di più sui metodi operatore, vedi [Metodi operatore](/guida-al-linguaggio/operatori-avanzati.md#metodi-operatore).

## Trailing closure <a href="#trailing-closure" id="trailing-closure"></a>

Se devi passare un'espressione closure a una funzione come ultimo argomento della funzione e l'espressione closure è lunga, può essere utile scriverla invece come *trailing closure* (closure finale). Scrivi una trailing closure dopo le parentesi della chiamata di funzione, anche se la trailing closure è comunque un argomento della funzione. Quando usi la sintassi delle trailing closure, non scrivi l'etichetta dell'argomento per la prima closure come parte della chiamata di funzione. Una chiamata di funzione può includere più trailing closure; tuttavia, i primi esempi seguenti usano un'unica trailing closure.

```swift
func someFunctionThatTakesAClosure(closure: () -> Void) {
    // qui va il corpo della funzione
}

// Ecco come chiami questa funzione senza usare una trailing closure:

someFunctionThatTakesAClosure(closure: {
    // qui va il corpo della closure
})

// Ecco invece come chiami questa funzione con una trailing closure:

someFunctionThatTakesAClosure() {
    // qui va il corpo della trailing closure
}
```

La closure di ordinamento di stringhe della sezione [Sintassi delle espressioni closure](/guida-al-linguaggio/closure.md#sintassi-delle-espressioni-closure) vista sopra può essere scritta al di fuori delle parentesi del metodo `sorted(by:)` come trailing closure:

```swift
reversedNames = names.sorted() { $0 > $1 }
```

Se un'espressione closure viene fornita come unico argomento della funzione o del metodo e fornisci quell'espressione come trailing closure, non hai bisogno di scrivere una coppia di parentesi `()` dopo il nome della funzione o del metodo quando chiami la funzione:

```swift
reversedNames = names.sorted { $0 > $1 }
```

Le trailing closure sono più utili quando la closure è abbastanza lunga da non poter essere scritta inline su un'unica riga. Per esempio, il tipo `Array` di Swift ha un metodo `map(_:)`, che accetta un'espressione closure come unico argomento. La closure viene chiamata una volta per ciascun elemento dell'array, e restituisce per quell'elemento un valore mappato alternativo (eventualmente di un altro tipo). Specifichi la natura della mappatura e il tipo del valore restituito scrivendo codice nella closure che passi a `map(_:)`.

Dopo aver applicato la closure fornita a ciascun elemento dell'array, il metodo `map(_:)` restituisce un nuovo array contenente tutti i nuovi valori mappati, nello stesso ordine dei valori corrispondenti nell'array originale.

Ecco come puoi usare il metodo `map(_:)` con una trailing closure per convertire un array di valori `Int` in un array di valori `String`. L'array `[16, 58, 510]` viene usato per creare il nuovo array `["OneSix", "FiveEight", "FiveOneZero"]`:

```swift
let digitNames = [
    0: "Zero", 1: "One", 2: "Two",   3: "Three", 4: "Four",
    5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
]
let numbers = [16, 58, 510]
```

Il codice qui sopra crea un dizionario che associa le cifre intere alle versioni in lingua inglese dei loro nomi. Definisce inoltre un array di interi, pronti per essere convertiti in stringhe.

Ora puoi usare l'array `numbers` per creare un array di valori `String`, passando un'espressione closure al metodo `map(_:)` dell'array come trailing closure:

```swift
let strings = numbers.map { (number) -> String in
    var number = number
    var output = ""
    repeat {
        output = digitNames[number % 10]! + output
        number /= 10
    } while number > 0
    return output
}
// il tipo di strings viene inferito come [String]
// il suo valore è ["OneSix", "FiveEight", "FiveOneZero"]
```

Il metodo `map(_:)` chiama l'espressione closure una volta per ciascun elemento dell'array. Non hai bisogno di specificare il tipo del parametro di input della closure, `number`, perché il tipo può essere inferito dai valori dell'array da mappare.

In questo esempio, la variabile `number` viene inizializzata con il valore del parametro `number` della closure, in modo che il valore possa essere modificato all'interno del corpo della closure. (I parametri di funzioni e closure sono sempre costanti.) L'espressione closure specifica anche un tipo di ritorno `String`, per indicare il tipo che verrà memorizzato nell'array di output mappato.

L'espressione closure costruisce una stringa chiamata `output` ogni volta che viene chiamata. Calcola l'ultima cifra di `number` usando l'operatore di resto (`number % 10`), e usa questa cifra per cercare una stringa appropriata nel dizionario `digitNames`. La closure può essere usata per creare una rappresentazione in forma di stringa di qualsiasi intero maggiore di zero.

{% hint style="info" %}
**Nota:** La chiamata al subscript del dizionario `digitNames` è seguita da un punto esclamativo (`!`), perché i subscript dei dizionari restituiscono un valore opzionale per indicare che la ricerca nel dizionario può fallire se la chiave non esiste. Nell'esempio qui sopra, è garantito che `number % 10` sarà sempre una chiave di subscript valida per il dizionario `digitNames`, e quindi si usa un punto esclamativo per forzare l'unwrapping del valore `String` memorizzato nel valore di ritorno opzionale del subscript.
{% endhint %}

La stringa recuperata dal dizionario `digitNames` viene aggiunta all'*inizio* di `output`, costruendo di fatto una versione in forma di stringa del numero al contrario. (L'espressione `number % 10` dà un valore di `6` per `16`, `8` per `58` e `0` per `510`.)

La variabile `number` viene poi divisa per `10`. Poiché è un intero, viene arrotondata per difetto durante la divisione, quindi `16` diventa `1`, `58` diventa `5` e `510` diventa `51`.

Il processo viene ripetuto finché `number` non è uguale a `0`, momento in cui la stringa `output` viene restituita dalla closure, e viene aggiunta all'array di output dal metodo `map(_:)`.

L'uso della sintassi delle trailing closure nell'esempio qui sopra incapsula in modo ordinato la funzionalità della closure subito dopo la funzione che quella closure supporta, senza bisogno di racchiudere l'intera closure all'interno delle parentesi esterne del metodo `map(_:)`.

Se una funzione accetta più closure, ometti l'etichetta dell'argomento per la prima trailing closure ed etichetti le trailing closure rimanenti. Per esempio, la funzione seguente carica un'immagine per una galleria fotografica:

```swift
func loadPicture(from server: Server, completion: (Picture) -> Void, onFailure: () -> Void) {
    if let picture = download("photo.jpg", from: server) {
        completion(picture)
    } else {
        onFailure()
    }
}
```

Quando chiami questa funzione per caricare un'immagine, fornisci due closure. La prima closure è un gestore di completamento che mostra un'immagine dopo un download riuscito. La seconda closure è un gestore di errori che mostra un errore all'utente.

```swift
loadPicture(from: someServer) { picture in
    someView.currentPicture = picture
} onFailure: {
    print("Couldn't download the next picture.")
}
```

In questo esempio, la funzione `loadPicture(from:completion:onFailure:)` affida il suo compito di rete a un'esecuzione in background, e chiama uno dei due gestori di completamento quando il compito di rete termina. Scrivere la funzione in questo modo ti permette di separare in modo pulito il codice responsabile della gestione di un errore di rete dal codice che aggiorna l'interfaccia utente dopo un download riuscito, invece di usare un'unica closure che gestisce entrambe le circostanze.

{% hint style="info" %}
**Nota:** I gestori di completamento possono diventare difficili da leggere, soprattutto quando devi annidare più gestori. Un approccio alternativo consiste nell'usare codice asincrono, come descritto in [Concorrenza](/guida-al-linguaggio/concorrenza.md).
{% endhint %}

## Catturare valori <a href="#catturare-valori" id="catturare-valori"></a>

Una closure può *catturare* costanti e variabili dal contesto circostante in cui è definita. La closure può quindi fare riferimento ai valori di quelle costanti e variabili e modificarli dall'interno del suo corpo, anche se l'ambito originale che ha definito le costanti e le variabili non esiste più.

In Swift, la forma più semplice di closure in grado di catturare valori è una funzione annidata, scritta all'interno del corpo di un'altra funzione. Una funzione annidata può catturare qualsiasi argomento della sua funzione esterna e può anche catturare qualsiasi costante e variabile definita all'interno della funzione esterna.

Ecco un esempio di una funzione chiamata `makeIncrementer`, che contiene una funzione annidata chiamata `incrementer`. La funzione annidata `incrementer()` cattura due valori, `runningTotal` e `amount`, dal suo contesto circostante. Dopo aver catturato questi valori, `incrementer` viene restituita da `makeIncrementer` come una closure che incrementa `runningTotal` di `amount` ogni volta che viene chiamata.

```swift
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementer() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementer
}
```

Il tipo di ritorno di `makeIncrementer` è `() -> Int`. Ciò significa che restituisce una *funzione*, anziché un semplice valore. La funzione che restituisce non ha parametri, e restituisce un valore `Int` ogni volta che viene chiamata. Per imparare come le funzioni possano restituire altre funzioni, vedi [Tipi funzione come tipi di ritorno](/guida-al-linguaggio/funzioni.md#tipi-funzione-come-tipi-di-ritorno).

La funzione `makeIncrementer(forIncrement:)` definisce una variabile intera chiamata `runningTotal`, per memorizzare il totale progressivo corrente dell'incrementatore che verrà restituito. Questa variabile viene inizializzata con un valore di `0`.

La funzione `makeIncrementer(forIncrement:)` ha un unico parametro `Int` con etichetta dell'argomento `forIncrement` e nome del parametro `amount`. Il valore dell'argomento passato a questo parametro specifica di quanto deve essere incrementato `runningTotal` ogni volta che viene chiamata la funzione incrementatrice restituita. La funzione `makeIncrementer` definisce una funzione annidata chiamata `incrementer`, che esegue l'incremento vero e proprio. Questa funzione si limita ad aggiungere `amount` a `runningTotal` e a restituire il risultato.

Se considerata isolatamente, la funzione annidata `incrementer()` potrebbe sembrare insolita:

```swift
func incrementer() -> Int {
    runningTotal += amount
    return runningTotal
}
```

La funzione `incrementer()` non ha alcun parametro, eppure fa riferimento a `runningTotal` e `amount` dall'interno del suo corpo. Lo fa catturando un *riferimento* a `runningTotal` e `amount` dalla funzione circostante e usandoli all'interno del proprio corpo. La cattura per riferimento garantisce che `runningTotal` e `amount` non scompaiano quando la chiamata a `makeIncrementer` termina, e garantisce inoltre che `runningTotal` sia disponibile la volta successiva in cui viene chiamata la funzione `incrementer`.

{% hint style="info" %}
**Nota:** Come ottimizzazione, Swift può invece catturare e memorizzare una *copia* di un valore se quel valore non viene mutato da una closure, e se il valore non viene mutato dopo la creazione della closure.

Swift gestisce inoltre tutta la gestione della memoria legata all'eliminazione delle variabili quando non sono più necessarie.
{% endhint %}

Ecco un esempio di `makeIncrementer` in azione:

```swift
let incrementByTen = makeIncrementer(forIncrement: 10)
```

Questo esempio imposta una costante chiamata `incrementByTen` in modo che faccia riferimento a una funzione incrementatrice che aggiunge `10` alla sua variabile `runningTotal` ogni volta che viene chiamata. Chiamare la funzione più volte mostra questo comportamento in azione:

```swift
incrementByTen()
// restituisce un valore di 10
incrementByTen()
// restituisce un valore di 20
incrementByTen()
// restituisce un valore di 30
```

Se crei un secondo incrementatore, avrà il proprio riferimento memorizzato a una nuova e distinta variabile `runningTotal`:

```swift
let incrementBySeven = makeIncrementer(forIncrement: 7)
incrementBySeven()
// restituisce un valore di 7
```

Chiamare di nuovo l'incrementatore originale (`incrementByTen`) continua a incrementare la sua variabile `runningTotal`, e non influisce sulla variabile catturata da `incrementBySeven`:

```swift
incrementByTen()
// restituisce un valore di 40
```

{% hint style="info" %}
**Nota:** Se assegni una closure a una proprietà di un'istanza di classe, e la closure cattura quell'istanza facendo riferimento all'istanza o ai suoi membri, creerai un ciclo di riferimenti forti tra la closure e l'istanza. Swift usa le *liste di cattura* per interrompere questi cicli di riferimenti forti. Per maggiori informazioni, vedi [Cicli di riferimenti forti per le closure](/guida-al-linguaggio/conteggio-automatico-dei-riferimenti.md#cicli-di-riferimenti-forti-per-le-closure).
{% endhint %}

## Le closure sono tipi riferimento <a href="#le-closure-sono-tipi-riferimento" id="le-closure-sono-tipi-riferimento"></a>

Nell'esempio qui sopra, `incrementBySeven` e `incrementByTen` sono costanti, ma le closure a cui queste costanti fanno riferimento sono comunque in grado di incrementare le variabili `runningTotal` che hanno catturato. Questo perché funzioni e closure sono *tipi riferimento*.

Ogni volta che assegni una funzione o una closure a una costante o a una variabile, in realtà imposti quella costante o variabile come *riferimento* alla funzione o alla closure. Nell'esempio qui sopra, è la scelta della closure a cui `incrementByTen` *fa riferimento* a essere costante, e non il contenuto della closure stessa.

Ciò significa anche che se assegni una closure a due costanti o variabili diverse, entrambe quelle costanti o variabili fanno riferimento alla stessa closure.

```swift
let alsoIncrementByTen = incrementByTen
alsoIncrementByTen()
// restituisce un valore di 50

incrementByTen()
// restituisce un valore di 60
```

L'esempio qui sopra mostra che chiamare `alsoIncrementByTen` equivale a chiamare `incrementByTen`. Poiché entrambe fanno riferimento alla stessa closure, incrementano e restituiscono entrambe lo stesso totale progressivo.

## Closure escaping <a href="#closure-escaping" id="closure-escaping"></a>

Si dice che una closure *sfugge* (escape) a una funzione quando la closure viene passata come argomento alla funzione, ma viene chiamata dopo che la funzione ha restituito il controllo. Quando dichiari una funzione che accetta una closure come uno dei suoi parametri, puoi scrivere `@escaping` prima del tipo del parametro per indicare che alla closure è consentito sfuggire.

Un modo in cui una closure può sfuggire è venire memorizzata in una variabile definita al di fuori della funzione. Per esempio, molte funzioni che avviano un'operazione asincrona accettano un argomento closure come gestore di completamento. La funzione restituisce il controllo dopo aver avviato l'operazione, ma la closure non viene chiamata finché l'operazione non è completata — la closure deve sfuggire, per essere chiamata in seguito. Per esempio:

```swift
var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
    completionHandlers.append(completionHandler)
}
```

La funzione `someFunctionWithEscapingClosure(_:)` accetta una closure come argomento e la aggiunge a un array dichiarato al di fuori della funzione. Se non contrassegnassi il parametro di questa funzione con `@escaping`, otterresti un errore in fase di compilazione.

Una closure escaping che fa riferimento a `self` richiede un'attenzione particolare se `self` fa riferimento a un'istanza di una classe. Catturare `self` in una closure escaping rende facile creare accidentalmente un ciclo di riferimenti forti. Per informazioni sui cicli di riferimenti, vedi [Conteggio automatico dei riferimenti](/guida-al-linguaggio/conteggio-automatico-dei-riferimenti.md).

Normalmente, una closure cattura le variabili implicitamente usandole nel corpo della closure, ma in questo caso devi essere esplicito. Se vuoi catturare `self`, scrivi `self` esplicitamente quando lo usi, oppure includi `self` nella lista di cattura della closure. Scrivere `self` esplicitamente ti permette di esprimere la tua intenzione, e ti ricorda di verificare che non ci sia un ciclo di riferimenti. Per esempio, nel codice seguente, la closure passata a `someFunctionWithEscapingClosure(_:)` fa riferimento a `self` esplicitamente. Al contrario, la closure passata a `someFunctionWithNonescapingClosure(_:)` è una closure non-escaping, il che significa che può fare riferimento a `self` implicitamente.

```swift
func someFunctionWithNonescapingClosure(closure: () -> Void) {
    closure()
}

class SomeClass {
    var x = 10
    func doSomething() {
        someFunctionWithEscapingClosure { self.x = 100 }
        someFunctionWithNonescapingClosure { x = 200 }
    }
}

let instance = SomeClass()
instance.doSomething()
print(instance.x)
// Stampa "200".

completionHandlers.first?()
print(instance.x)
// Stampa "100".
```

Ecco una versione di `doSomething()` che cattura `self` includendolo nella lista di cattura della closure, e poi fa riferimento a `self` implicitamente:

```swift
class SomeOtherClass {
    var x = 10
    func doSomething() {
        someFunctionWithEscapingClosure { [self] in x = 100 }
        someFunctionWithNonescapingClosure { x = 200 }
    }
}
```

Se `self` è un'istanza di una struttura o di un'enumerazione, puoi sempre fare riferimento a `self` implicitamente. Tuttavia, una closure escaping non può catturare un riferimento mutabile a `self` quando `self` è un'istanza di una struttura o di un'enumerazione. Strutture ed enumerazioni non consentono la mutabilità condivisa, come discusso in [Strutture ed enumerazioni sono tipi valore](/guida-al-linguaggio/strutture-e-classi.md#strutture-ed-enumerazioni-sono-tipi-valore).

```swift
struct SomeStruct {
    var x = 10
    mutating func doSomething() {
        someFunctionWithNonescapingClosure { x = 200 }  // OK
        someFunctionWithEscapingClosure { x = 100 }     // Errore
    }
}
```

La chiamata alla funzione `someFunctionWithEscapingClosure` nell'esempio qui sopra è un errore perché si trova all'interno di un metodo mutating, quindi `self` è mutabile. Questo viola la regola secondo cui le closure escaping non possono catturare un riferimento mutabile a `self` per le strutture.

## Autoclosure <a href="#autoclosure" id="autoclosure"></a>

Un'*autoclosure* è una closure creata automaticamente per racchiudere un'espressione passata come argomento a una funzione. Non accetta alcun argomento, e quando viene chiamata, restituisce il valore dell'espressione racchiusa al suo interno. Questa comodità sintattica ti permette di omettere le parentesi graffe attorno al parametro di una funzione scrivendo un'espressione normale invece di una closure esplicita.

È comune *chiamare* funzioni che accettano autoclosure, ma non è comune *implementare* quel tipo di funzione. Per esempio, la funzione `assert(condition:message:file:line:)` accetta un'autoclosure per i suoi parametri `condition` e `message`; il suo parametro `condition` viene valutato solo nelle build di debug e il suo parametro `message` viene valutato solo se `condition` è `false`.

Un'autoclosure ti permette di ritardare la valutazione, perché il codice al suo interno non viene eseguito finché non chiami la closure. Ritardare la valutazione è utile per il codice che ha effetti collaterali o è computazionalmente costoso, perché ti permette di controllare quando quel codice viene valutato. Il codice seguente mostra come una closure ritardi la valutazione.

```swift
var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
print(customersInLine.count)
// Stampa "5".

let customerProvider = { customersInLine.remove(at: 0) }
print(customersInLine.count)
// Stampa "5".

print("Now serving \(customerProvider())!")
// Stampa "Now serving Chris!"
print(customersInLine.count)
// Stampa "4".
```

Anche se il primo elemento dell'array `customersInLine` viene rimosso dal codice all'interno della closure, l'elemento dell'array non viene rimosso finché la closure non viene effettivamente chiamata. Se la closure non viene mai chiamata, l'espressione all'interno della closure non viene mai valutata, il che significa che l'elemento dell'array non viene mai rimosso. Nota che il tipo di `customerProvider` non è `String` ma `() -> String` — una funzione senza parametri che restituisce una stringa.

Ottieni lo stesso comportamento di valutazione ritardata quando passi una closure come argomento a una funzione.

```swift
// customersInLine è ["Alex", "Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: () -> String) {
    print("Now serving \(customerProvider())!")
}
serve(customer: { customersInLine.remove(at: 0) } )
// Stampa "Now serving Alex!"
```

La funzione `serve(customer:)` nel listato qui sopra accetta una closure esplicita che restituisce il nome di un cliente. La versione di `serve(customer:)` seguente esegue la stessa operazione ma, invece di accettare una closure esplicita, accetta un'autoclosure contrassegnando il tipo del suo parametro con l'attributo `@autoclosure`. Ora puoi chiamare la funzione come se accettasse un argomento `String` invece di una closure. L'argomento viene convertito automaticamente in una closure, perché il tipo del parametro `customerProvider` è contrassegnato con l'attributo `@autoclosure`.

```swift
// customersInLine è ["Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: @autoclosure () -> String) {
    print("Now serving \(customerProvider())!")
}
serve(customer: customersInLine.remove(at: 0))
// Stampa "Now serving Ewa!"
```

{% hint style="info" %}
**Nota:** L'abuso delle autoclosure può rendere il tuo codice difficile da comprendere. Il contesto e il nome della funzione dovrebbero rendere chiaro che la valutazione viene rinviata.
{% endhint %}

Se vuoi un'autoclosure a cui sia consentito sfuggire, usa sia l'attributo `@autoclosure` sia l'attributo `@escaping`. L'attributo `@escaping` è descritto sopra in [Closure escaping](/guida-al-linguaggio/closure.md#closure-escaping).

```swift
// customersInLine è ["Barry", "Daniella"]
var customerProviders: [() -> String] = []
func collectCustomerProviders(_ customerProvider: @autoclosure @escaping () -> String) {
    customerProviders.append(customerProvider)
}
collectCustomerProviders(customersInLine.remove(at: 0))
collectCustomerProviders(customersInLine.remove(at: 0))

print("Collected \(customerProviders.count) closures.")
// Stampa "Collected 2 closures."
for customerProvider in customerProviders {
    print("Now serving \(customerProvider())!")
}
// Stampa "Now serving Barry!"
// Stampa "Now serving Daniella!"
```

Nel codice qui sopra, invece di chiamare la closure che le viene passata come argomento `customerProvider`, la funzione `collectCustomerProviders(_:)` aggiunge la closure all'array `customerProviders`. L'array è dichiarato al di fuori dell'ambito della funzione, il che significa che le closure nell'array possono essere eseguite dopo che la funzione ha restituito il controllo. Di conseguenza, al valore dell'argomento `customerProvider` deve essere consentito di sfuggire all'ambito della funzione.
