> 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/riferimento-del-linguaggio/espressioni.md).

# Espressioni (Expressions)

Accedi ai valori, modificali e assegnali.

In Swift esistono quattro tipi di espressioni: espressioni prefisse, espressioni infisse, espressioni primarie ed espressioni postfisse. Valutare un'espressione restituisce un valore, causa un effetto collaterale, o entrambe le cose.

Le espressioni prefisse e infisse ti permettono di applicare operatori a espressioni più piccole. Le espressioni primarie sono concettualmente il tipo più semplice di espressione e forniscono un modo per accedere ai valori. Le espressioni postfisse, come le espressioni prefisse e infisse, ti permettono di costruire espressioni più complesse usando postfissi come le chiamate di funzione e l'accesso ai membri. Ciascun tipo di espressione è descritto in dettaglio nelle sezioni seguenti.

{% hint style="info" %}
**Grammatica di un'espressione:**

*expression* → *try-operator?* *await-operator?* *prefix-expression* *infix-expressions?*
{% endhint %}

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

Le *espressioni prefisse* combinano un operatore prefisso facoltativo con un'espressione. Gli operatori prefissi accettano un solo argomento, l'espressione che li segue.

Per informazioni sul comportamento di questi operatori, vedi [Operatori di base](/guida-al-linguaggio/operatori-di-base.md) e [Operatori avanzati](/guida-al-linguaggio/operatori-avanzati.md).

Per informazioni sugli operatori forniti dalla libreria standard di Swift, vedi [Operator Declarations](https://developer.apple.com/documentation/swift/operator_declarations).

{% hint style="info" %}
**Grammatica di un'espressione prefissa:**

*prefix-expression* → *prefix-operator?* *postfix-expression*\
*prefix-expression* → *in-out-expression*
{% endhint %}

### Espressione in-out <a href="#espressione-in-out" id="espressione-in-out"></a>

Un'*espressione in-out* contrassegna una variabile che viene passata come argomento in-out a un'espressione di chiamata di funzione.

```swift
&<#expression#>
```

Per maggiori informazioni sui parametri in-out e per vedere un esempio, vedi [Parametri in-out](/guida-al-linguaggio/funzioni.md#parametri-in-out).

Le espressioni in-out sono usate anche quando si fornisce un argomento che non è un puntatore in un contesto in cui è richiesto un puntatore, come descritto in [Conversione implicita in un tipo puntatore](/riferimento-del-linguaggio/espressioni.md#conversione-implicita-in-un-tipo-puntatore).

{% hint style="info" %}
**Grammatica di un'espressione in-out:**

*in-out-expression* → **`&`** *primary-expression*
{% endhint %}

### Operatore try <a href="#operatore-try" id="operatore-try"></a>

Un'*espressione try* è costituita dall'operatore `try` seguito da un'espressione che può lanciare un errore. Ha la forma seguente:

```swift
try <#expression#>
```

Il valore di un'espressione `try` è il valore dell'*expression*.

Un'*espressione optional-try* è costituita dall'operatore `try?` seguito da un'espressione che può lanciare un errore. Ha la forma seguente:

```swift
try? <#expression#>
```

Se l'*expression* non lancia un errore, il valore dell'espressione optional-try è un opzionale che contiene il valore dell'*expression*. Altrimenti, il valore dell'espressione optional-try è `nil`.

Un'*espressione forced-try* è costituita dall'operatore `try!` seguito da un'espressione che può lanciare un errore. Ha la forma seguente:

```swift
try! <#expression#>
```

Il valore di un'espressione forced-try è il valore dell'*expression*. Se l'*expression* lancia un errore, viene prodotto un errore in fase di esecuzione.

Quando l'espressione sul lato sinistro di un operatore infisso è contrassegnata con `try`, `try?` o `try!`, quell'operatore si applica all'intera espressione infissa. Detto questo, puoi usare le parentesi per rendere esplicito l'ambito di applicazione dell'operatore.

```swift
// Scrivere 'try' si applica a entrambe le chiamate di funzione.
sum = try someThrowingFunction() + anotherThrowingFunction()

// Scrivere 'try' si applica a entrambe le chiamate di funzione.
sum = try (someThrowingFunction() + anotherThrowingFunction())

// Errore: scrivere 'try' si applica solo alla prima chiamata di funzione.
sum = (try someThrowingFunction()) + anotherThrowingFunction()
```

Un'espressione `try` non può comparire sul lato destro di un operatore infisso, a meno che l'operatore infisso non sia l'operatore di assegnazione o l'espressione `try` non sia racchiusa tra parentesi.

Se un'espressione include sia l'operatore `try` sia l'operatore `await`, l'operatore `try` deve comparire per primo.

Per maggiori informazioni e per vedere esempi di come usare `try`, `try?` e `try!`, vedi [Gestione degli errori](/guida-al-linguaggio/gestione-degli-errori.md).

{% hint style="info" %}
**Grammatica di un'espressione try:**

*try-operator* → **`try`** | **`try`** **`?`** | **`try`** **`!`**
{% endhint %}

### Operatore await <a href="#operatore-await" id="operatore-await"></a>

Un'*espressione await* è costituita dall'operatore `await` seguito da un'espressione che usa il risultato di un'operazione asincrona. Ha la forma seguente:

```swift
await <#expression#>
```

Il valore di un'espressione `await` è il valore dell'*expression*.

Un'espressione contrassegnata con `await` è chiamata *potenziale punto di sospensione*. L'esecuzione di una funzione asincrona può essere sospesa in corrispondenza di ciascuna espressione contrassegnata con `await`. Inoltre, l'esecuzione del codice concorrente non viene mai sospesa in nessun altro punto. Ciò significa che il codice tra potenziali punti di sospensione può aggiornare in sicurezza uno stato che richiede di violare temporaneamente degli invarianti, a condizione che completi l'aggiornamento prima del potenziale punto di sospensione successivo.

Un'espressione `await` può comparire solo all'interno di un contesto asincrono, come la trailing closure passata alla funzione `async(priority:operation:)`. Non può comparire nel corpo di un'istruzione `defer`, né in un'autoclosure di tipo funzione sincrona.

Quando l'espressione sul lato sinistro di un operatore infisso è contrassegnata con l'operatore `await`, quell'operatore si applica all'intera espressione infissa. Detto questo, puoi usare le parentesi per rendere esplicito l'ambito di applicazione dell'operatore.

```swift
// Scrivere 'await' si applica a entrambe le chiamate di funzione.
sum = await someAsyncFunction() + anotherAsyncFunction()

// Scrivere 'await' si applica a entrambe le chiamate di funzione.
sum = await (someAsyncFunction() + anotherAsyncFunction())

// Errore: scrivere 'await' si applica solo alla prima chiamata di funzione.
sum = (await someAsyncFunction()) + anotherAsyncFunction()
```

Un'espressione `await` non può comparire sul lato destro di un operatore infisso, a meno che l'operatore infisso non sia l'operatore di assegnazione o l'espressione `await` non sia racchiusa tra parentesi.

Se un'espressione include sia l'operatore `await` sia l'operatore `try`, l'operatore `try` deve comparire per primo.

{% hint style="info" %}
**Grammatica di un'espressione await:**

*await-operator* → **`await`**
{% endhint %}

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

Le *espressioni infisse* combinano un operatore binario infisso con l'espressione che esso accetta come argomenti sinistro e destro. Hanno la forma seguente:

```swift
<#left-hand argument#> <#operator#> <#right-hand argument#>
```

Per informazioni sul comportamento di questi operatori, vedi [Operatori di base](/guida-al-linguaggio/operatori-di-base.md) e [Operatori avanzati](/guida-al-linguaggio/operatori-avanzati.md).

Per informazioni sugli operatori forniti dalla libreria standard di Swift, vedi [Operator Declarations](https://developer.apple.com/documentation/swift/operator_declarations).

{% hint style="info" %}
**Nota:** In fase di analisi sintattica, un'espressione composta da operatori infissi è rappresentata come una lista piatta. Questa lista viene trasformata in un albero applicando la precedenza degli operatori. Per esempio, l'espressione `2 + 3 * 5` viene inizialmente interpretata come una lista piatta di cinque elementi, `2`, `+`, `3`, `*` e `5`. Questo processo la trasforma nell'albero (2 + (3 \* 5)).
{% endhint %}

{% hint style="info" %}
**Grammatica di un'espressione infissa:**

*infix-expression* → *infix-operator* *prefix-expression*\
*infix-expression* → *assignment-operator* *try-operator?* *await-operator?* *prefix-expression*\
*infix-expression* → *conditional-operator* *try-operator?* *await-operator?* *prefix-expression*\
*infix-expression* → *type-casting-operator*\
*infix-expressions* → *infix-expression* *infix-expressions?*
{% endhint %}

### Operatore di assegnazione <a href="#operatore-di-assegnazione" id="operatore-di-assegnazione"></a>

L'*operatore di assegnazione* imposta un nuovo valore per una data espressione. Ha la forma seguente:

```swift
<#expression#> = <#value#>
```

Il valore dell'*expression* viene impostato al valore ottenuto valutando il *value*. Se l'*expression* è una tupla, il *value* deve essere una tupla con lo stesso numero di elementi. (Sono ammesse tuple annidate.) L'assegnazione viene eseguita da ciascuna parte del *value* alla parte corrispondente dell'*expression*. Per esempio:

```swift
(a, _, (b, c)) = ("test", 9.45, (12, 3))
// a vale "test", b vale 12, c vale 3, e 9.45 viene ignorato
```

L'operatore di assegnazione non restituisce alcun valore.

{% hint style="info" %}
**Grammatica di un operatore di assegnazione:**

*assignment-operator* → **`=`**
{% endhint %}

### Operatore condizionale ternario <a href="#operatore-condizionale-ternario" id="operatore-condizionale-ternario"></a>

L'*operatore condizionale ternario* restituisce uno di due valori dati in base al valore di una condizione. Ha la forma seguente:

```swift
<#condition#> ? <#expression used if true#> : <#expression used if false#>
```

Se la *condition* viene valutata come `true`, l'operatore condizionale valuta la prima espressione e ne restituisce il valore. Altrimenti, valuta la seconda espressione e ne restituisce il valore. L'espressione non usata non viene valutata.

Per un esempio che usa l'operatore condizionale ternario, vedi [Operatore condizionale ternario](/guida-al-linguaggio/operatori-di-base.md#operatore-condizionale-ternario).

{% hint style="info" %}
**Grammatica di un operatore condizionale:**

*conditional-operator* → **`?`** *expression* **`:`**
{% endhint %}

### Operatori di type casting <a href="#operatori-di-type-casting" id="operatori-di-type-casting"></a>

Esistono quattro operatori di type casting: l'operatore `is`, l'operatore `as`, l'operatore `as?` e l'operatore `as!`.

Hanno la forma seguente:

```swift
<#expression#> is <#type#>
<#expression#> as <#type#>
<#expression#> as? <#type#>
<#expression#> as! <#type#>
```

L'operatore `is` verifica in fase di esecuzione se l'*expression* può essere convertita nel *type* specificato. Restituisce `true` se l'*expression* può essere convertita nel *type* specificato; altrimenti, restituisce `false`.

L'operatore `as` esegue una conversione quando è noto in fase di compilazione che la conversione riesce sempre, come nel caso dell'upcasting o del bridging. L'upcasting ti permette di usare un'espressione come istanza del supertipo del suo tipo, senza usare una variabile intermedia. Gli approcci seguenti sono equivalenti:

```swift
func f(_ any: Any) { print("Function for Any") }
func f(_ int: Int) { print("Function for Int") }
let x = 10
f(x)
// Stampa "Function for Int".

let y: Any = x
f(y)
// Stampa "Function for Any".

f(x as Any)
// Stampa "Function for Any".
```

Il bridging ti permette di usare un'espressione di un tipo della libreria standard di Swift come `String` come il suo tipo Foundation corrispondente come `NSString` senza dover creare una nuova istanza. Per maggiori informazioni sul bridging, vedi [Working with Foundation Types](https://developer.apple.com/documentation/swift/imported_c_and_objective_c_apis/working_with_foundation_types).

L'operatore `as?` esegue una conversione condizionale dell'*expression* nel *type* specificato. L'operatore `as?` restituisce un opzionale del *type* specificato. In fase di esecuzione, se la conversione riesce, il valore dell'*expression* viene racchiuso in un opzionale e restituito; altrimenti, il valore restituito è `nil`. Se la conversione nel *type* specificato è garantito che fallisca o è garantito che riesca, viene generato un errore in fase di compilazione.

L'operatore `as!` esegue una conversione forzata dell'*expression* nel *type* specificato. L'operatore `as!` restituisce un valore del *type* specificato, non un tipo opzionale. Se la conversione fallisce, viene generato un errore in fase di esecuzione. Il comportamento di `x as! T` è lo stesso di `(x as? T)!`.

Per maggiori informazioni sul type casting e per vedere esempi che usano gli operatori di type casting, vedi [Type casting](/guida-al-linguaggio/type-casting.md).

{% hint style="info" %}
**Grammatica di un operatore di type casting:**

*type-casting-operator* → **`is`** *type*\
*type-casting-operator* → **`as`** *type*\
*type-casting-operator* → **`as`** **`?`** *type*\
*type-casting-operator* → **`as`** **`!`** *type*
{% endhint %}

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

Le *espressioni primarie* sono il tipo più elementare di espressione. Possono essere usate come espressioni a sé stanti e possono essere combinate con altri token per formare espressioni prefisse, espressioni infisse ed espressioni postfisse.

{% hint style="info" %}
**Grammatica di un'espressione primaria:**

*primary-expression* → *identifier* *generic-argument-clause?*\
*primary-expression* → *literal-expression*\
*primary-expression* → *self-expression*\
*primary-expression* → *superclass-expression*\
*primary-expression* → *conditional-expression*\
*primary-expression* → *closure-expression*\
*primary-expression* → *parenthesized-expression*\
*primary-expression* → *tuple-expression*\
*primary-expression* → *implicit-member-expression*\
*primary-expression* → *wildcard-expression*\
*primary-expression* → *macro-expansion-expression*\
*primary-expression* → *key-path-expression*\
*primary-expression* → *selector-expression*\
*primary-expression* → *key-path-string-expression*
{% endhint %}

### Espressione letterale <a href="#espressione-letterale" id="espressione-letterale"></a>

Un'*espressione letterale* è costituita da un letterale ordinario (come una stringa o un numero), da un letterale array o dizionario, oppure da un letterale playground.

{% hint style="info" %}
**Nota:** Prima di Swift 5.9, erano riconosciuti i seguenti letterali speciali: `#column`, `#dsohandle`, `#fileID`, `#filePath`, `#file`, `#function` e `#line`. Questi sono ora implementati come macro nella libreria standard di Swift: [`column()`](https://developer.apple.com/documentation/swift/column\(\)), [`dsohandle()`](https://developer.apple.com/documentation/swift/dsohandle\(\)), [`fileID()`](https://developer.apple.com/documentation/swift/fileID\(\)), [`filePath()`](https://developer.apple.com/documentation/swift/filePath\(\)), [`file()`](https://developer.apple.com/documentation/swift/file\(\)), [`function()`](https://developer.apple.com/documentation/swift/function\(\)) e [`line()`](https://developer.apple.com/documentation/swift/line\(\)).
{% endhint %}

Un *letterale array* è una collezione ordinata di valori. Ha la forma seguente:

```swift
[<#value 1#>, <#value 2#>, <#...#>]
```

L'ultima espressione nell'array può essere seguita da una virgola facoltativa. Il valore di un letterale array ha tipo `[T]`, dove `T` è il tipo delle espressioni al suo interno. Se ci sono espressioni di più tipi, `T` è il loro supertipo comune più vicino. I letterali array vuoti si scrivono usando una coppia di parentesi quadre vuote e possono essere usati per creare un array vuoto di un tipo specificato.

```swift
var emptyArray: [Double] = []
```

Un *letterale dizionario* è una collezione non ordinata di coppie chiave-valore. Ha la forma seguente:

```swift
[<#key 1#>: <#value 1#>, <#key 2#>: <#value 2#>, <#...#>]
```

L'ultima espressione nel dizionario può essere seguita da una virgola facoltativa. Il valore di un letterale dizionario ha tipo `[Key: Value]`, dove `Key` è il tipo delle sue espressioni chiave e `Value` è il tipo delle sue espressioni valore. Se ci sono espressioni di più tipi, `Key` e `Value` sono il supertipo comune più vicino per i rispettivi valori. Un letterale dizionario vuoto si scrive come due punti all'interno di una coppia di parentesi quadre (`[:]`) per distinguerlo da un letterale array vuoto. Puoi usare un letterale dizionario vuoto per creare un letterale dizionario vuoto di tipi chiave e valore specificati.

```swift
var emptyDictionary: [String: Double] = [:]
```

Un *letterale playground* è usato da Xcode per creare una rappresentazione interattiva di un colore, di un file o di un'immagine all'interno dell'editor del programma. I letterali playground in testo semplice al di fuori di Xcode sono rappresentati usando una speciale sintassi letterale.

Per informazioni sull'uso dei letterali playground in Xcode, vedi [Add a color, file, or image literal](https://help.apple.com/xcode/mac/current/#/dev4c60242fc) nell'Aiuto di Xcode.

{% hint style="info" %}
**Grammatica di un'espressione letterale:**

*literal-expression* → *literal*\
*literal-expression* → *array-literal* | *dictionary-literal* | *playground-literal*

*array-literal* → **`[`** *array-literal-items?* **`,`***?* **`]`**\
*array-literal-items* → *array-literal-item* | *array-literal-item* **`,`** *array-literal-items*\
*array-literal-item* → *expression*

*dictionary-literal* → **`[`** *dictionary-literal-items* **`,`***?* **`]`** | **`[`** **`:`** **`]`**\
*dictionary-literal-items* → *dictionary-literal-item* | *dictionary-literal-item* **`,`** *dictionary-literal-items*\
*dictionary-literal-item* → *expression* **`:`** *expression*

*playground-literal* → **`#colorLiteral`** **`(`** **`red`** **`:`** *expression* **`,`** **`green`** **`:`** *expression* **`,`** **`blue`** **`:`** *expression* **`,`** **`alpha`** **`:`** *expression* **`)`**\
*playground-literal* → **`#fileLiteral`** **`(`** **`resourceName`** **`:`** *expression* **`)`**\
*playground-literal* → **`#imageLiteral`** **`(`** **`resourceName`** **`:`** *expression* **`)`**
{% endhint %}

### Espressione self <a href="#espressione-self" id="espressione-self"></a>

L'espressione `self` è un riferimento esplicito al tipo corrente o all'istanza del tipo in cui compare. Ha le forme seguenti:

```swift
self
self.<#member name#>
self[<#subscript index#>]
self(<#initializer arguments#>)
self.init(<#initializer arguments#>)
```

In un inizializzatore, in un subscript o in un metodo di istanza, `self` fa riferimento all'istanza corrente del tipo in cui compare. In un metodo di tipo, `self` fa riferimento al tipo corrente in cui compare.

L'espressione `self` è usata per specificare l'ambito quando si accede ai membri, consentendo di disambiguare quando nell'ambito esiste un'altra variabile con lo stesso nome, come un parametro di funzione. Per esempio:

```swift
class SomeClass {
    var greeting: String
    init(greeting: String) {
        self.greeting = greeting
    }
}
```

In un metodo mutating di un tipo valore, puoi assegnare a `self` una nuova istanza di quel tipo valore. Per esempio:

```swift
struct Point {
    var x = 0.0, y = 0.0
    mutating func moveBy(x deltaX: Double, y deltaY: Double) {
        self = Point(x: x + deltaX, y: y + deltaY)
    }
}
```

{% hint style="info" %}
**Grammatica di un'espressione self:**

*self-expression* → **`self`** | *self-method-expression* | *self-subscript-expression* | *self-initializer-expression*

*self-method-expression* → **`self`** **`.`** *identifier*\
*self-subscript-expression* → **`self`** **`[`** *function-call-argument-list* **`]`**\
*self-initializer-expression* → **`self`** **`.`** **`init`**
{% endhint %}

### Espressione superclass <a href="#espressione-superclass" id="espressione-superclass"></a>

Un'*espressione superclass* permette a una classe di interagire con la sua superclasse. Ha una delle forme seguenti:

```swift
super.<#member name#>
super[<#subscript index#>]
super.init(<#initializer arguments#>)
```

La prima forma è usata per accedere a un membro della superclasse. La seconda forma è usata per accedere all'implementazione del subscript della superclasse. La terza forma è usata per accedere a un inizializzatore della superclasse.

Le sottoclassi possono usare un'espressione superclass nella loro implementazione di membri, subscript e inizializzatori per avvalersi dell'implementazione della loro superclasse.

{% hint style="info" %}
**Grammatica di un'espressione superclass:**

*superclass-expression* → *superclass-method-expression* | *superclass-subscript-expression* | *superclass-initializer-expression*

*superclass-method-expression* → **`super`** **`.`** *identifier*\
*superclass-subscript-expression* → **`super`** **`[`** *function-call-argument-list* **`]`**\
*superclass-initializer-expression* → **`super`** **`.`** **`init`**
{% endhint %}

### Espressione condizionale <a href="#espressione-condizionale" id="espressione-condizionale"></a>

Un'*espressione condizionale* restituisce uno tra diversi valori dati in base al valore di una condizione. Ha una delle forme seguenti:

```swift
if <#condition 1#> {
   <#expression used if condition 1 is true#>
} else if <#condition 2#> {
   <#expression used if condition 2 is true#>
} else {
   <#expression used if both conditions are false#>
}

switch <#expression#> {
case <#pattern 1#>:
    <#expression 1#>
case <#pattern 2#> where <#condition#>:
    <#expression 2#>
default:
    <#expression 3#>
}
```

Un'espressione condizionale ha lo stesso comportamento e la stessa sintassi di un'istruzione `if` o di un'istruzione `switch`, fatta eccezione per le differenze descritte nei paragrafi seguenti.

Un'espressione condizionale compare solo nei contesti seguenti:

* Come valore assegnato a una variabile.
* Come valore iniziale nella dichiarazione di una variabile o di una costante.
* Come errore lanciato da un'espressione `throw`.
* Come valore restituito da una funzione, da una closure o dal getter di una proprietà.
* Come valore all'interno di un ramo di un'espressione condizionale.

I rami di un'espressione condizionale sono esaustivi, il che garantisce che l'espressione produca sempre un valore indipendentemente dalla condizione. Ciò significa che ogni ramo `if` ha bisogno di un ramo `else` corrispondente.

Ogni ramo contiene una singola espressione, che viene usata come valore dell'espressione condizionale quando la condizione di quel ramo è vera, oppure un'istruzione `throw`, oppure una chiamata a una funzione che non restituisce mai.

Ogni ramo deve produrre un valore dello stesso tipo. Poiché il controllo dei tipi di ciascun ramo è indipendente, a volte è necessario specificare esplicitamente il tipo del valore, come quando i rami includono tipi diversi di letterali, o quando il valore di un ramo è `nil`. Quando devi fornire questa informazione, aggiungi un'annotazione di tipo alla variabile a cui viene assegnato il risultato, oppure aggiungi una conversione `as` ai valori dei rami.

```swift
let number: Double = if someCondition { 10 } else { 12.34 }
let number = if someCondition { 10 as Double } else { 12.34 }
```

All'interno di un result builder, le espressioni condizionali possono comparire solo come valore iniziale di una variabile o di una costante. Questo comportamento significa che quando scrivi `if` o `switch` in un result builder — al di fuori della dichiarazione di una variabile o di una costante — quel codice è interpretato come un'istruzione di diramazione e uno dei metodi del result builder trasforma quel codice.

Non inserire un'espressione condizionale in un'espressione `try`, anche se uno dei rami di un'espressione condizionale lancia errori.

{% hint style="info" %}
**Grammatica di un'espressione condizionale:**

*conditional-expression* → *if-expression* | *switch-expression*

*if-expression* → **`if`** *condition-list* **`{`** *statement* **`}`** *if-expression-tail*\
*if-expression-tail* → **`else`** *if-expression*\
*if-expression-tail* → **`else`** **`{`** *statement* **`}`**

*switch-expression* → **`switch`** *expression* **`{`** *switch-expression-cases* **`}`**\
*switch-expression-cases* → *switch-expression-case* *switch-expression-cases?*\
*switch-expression-case* → *case-label* *statement*\
*switch-expression-case* → *default-label* *statement*
{% endhint %}

### Espressione closure <a href="#espressione-closure" id="espressione-closure"></a>

Un'*espressione closure* crea una closure, nota anche come *lambda* o *funzione anonima* in altri linguaggi di programmazione. Come la dichiarazione di una funzione, una closure contiene istruzioni e cattura costanti e variabili dal suo ambito circostante. Ha la forma seguente:

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

I *parameters* hanno la stessa forma dei parametri nella dichiarazione di una funzione, come descritto in [Dichiarazione di funzione](/riferimento-del-linguaggio/dichiarazioni.md#dichiarazione-di-funzione).

Scrivere `throws` o `async` in un'espressione closure contrassegna esplicitamente una closure come throwing o asincrona.

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

Se il corpo di una closure include un'istruzione `throws` o un'espressione `try` che non è annidata all'interno di un'istruzione `do` con gestione esaustiva degli errori, la closure è considerata throwing. Se una closure throwing lancia errori di un solo tipo, la closure è considerata come una che lancia quel tipo di errore; altrimenti, è considerata come una che lancia `any Error`. Analogamente, se il corpo include un'espressione `await`, è considerata asincrona.

Esistono diverse forme speciali che permettono di scrivere le closure in modo più conciso:

* Una closure può omettere i tipi dei suoi parametri, il suo tipo di ritorno o entrambi. Se ometti i nomi dei parametri ed entrambi i tipi, ometti la parola chiave `in` prima delle istruzioni. Se i tipi omessi non possono essere inferiti, viene generato un errore in fase di compilazione.
* Una closure può omettere i nomi dei suoi parametri. I suoi parametri vengono allora chiamati implicitamente `$` seguito dalla loro posizione: `$0`, `$1`, `$2` e così via.
* Una closure costituita da una sola espressione è considerata come una che restituisce il valore di quell'espressione. Il contenuto di questa espressione viene inoltre preso in considerazione quando si esegue l'inferenza di tipo sull'espressione circostante.

Le espressioni closure seguenti sono equivalenti:

```swift
myFunction { (x: Int, y: Int) -> Int in
    return x + y
}

myFunction { x, y in
    return x + y
}

myFunction { return $0 + $1 }

myFunction { $0 + $1 }
```

Per informazioni sul passaggio di una closure come argomento a una funzione, vedi [Espressione di chiamata di funzione](/riferimento-del-linguaggio/espressioni.md#espressione-di-chiamata-di-funzione).

Le espressioni closure possono essere usate senza essere memorizzate in una variabile o in una costante, come quando usi immediatamente una closure come parte di una chiamata di funzione. Le espressioni closure passate a `myFunction` nel codice qui sopra sono esempi di questo tipo di uso immediato. Di conseguenza, il fatto che un'espressione closure sia escaping o non-escaping dipende dal contesto circostante dell'espressione. Un'espressione closure è non-escaping se viene chiamata immediatamente o passata come argomento di funzione non-escaping. Altrimenti, l'espressione closure è escaping.

Per maggiori informazioni sulle closure escaping, vedi [Closure escaping](/guida-al-linguaggio/closure.md#closure-escaping).

#### Liste di cattura <a href="#liste-di-cattura" id="liste-di-cattura"></a>

Per impostazione predefinita, un'espressione closure cattura costanti e variabili dal suo ambito circostante con riferimenti forti a quei valori. Puoi usare una *lista di cattura* per controllare esplicitamente come vengono catturati i valori in una closure.

Una lista di cattura si scrive come un elenco di espressioni separate da virgole racchiuso tra parentesi quadre, prima dell'elenco dei parametri. Se usi una lista di cattura, devi usare anche la parola chiave `in`, anche se ometti i nomi dei parametri, i tipi dei parametri e il tipo di ritorno. L'ultima espressione nella lista di cattura può essere seguita da una virgola facoltativa.

Le voci della lista di cattura vengono inizializzate quando la closure viene creata. Per ogni voce della lista di cattura, viene inizializzata una costante al valore della costante o della variabile che ha lo stesso nome nell'ambito circostante. Per esempio, nel codice seguente, `a` è inclusa nella lista di cattura ma `b` no, il che conferisce loro un comportamento diverso.

```swift
var a = 0
var b = 0
let closure = { [a] in
 print(a, b)
}

a = 10
b = 10
closure()
// Stampa "0 10".
```

Ci sono due cose diverse chiamate `a`, la variabile nell'ambito circostante e la costante nell'ambito della closure, ma una sola variabile chiamata `b`. La `a` nell'ambito interno viene inizializzata con il valore della `a` nell'ambito esterno quando la closure viene creata, ma i loro valori non sono collegati in alcun modo particolare. Ciò significa che una modifica al valore di `a` nell'ambito esterno non influisce sul valore di `a` nell'ambito interno, né una modifica ad `a` all'interno della closure influisce sul valore di `a` al di fuori della closure. Al contrario, c'è una sola variabile chiamata `b` — la `b` nell'ambito esterno — quindi le modifiche fatte dall'interno o dall'esterno della closure sono visibili in entrambi i punti.

Questa distinzione non è visibile quando il tipo della variabile catturata ha una semantica di riferimento. Per esempio, nel codice seguente ci sono due cose chiamate `x`, una variabile nell'ambito esterno e una costante nell'ambito interno, ma entrambe fanno riferimento allo stesso oggetto a causa della semantica di riferimento.

```swift
class SimpleClass {
    var value: Int = 0
}
var x = SimpleClass()
var y = SimpleClass()
let closure = { [x] in
    print(x.value, y.value)
}

x.value = 10
y.value = 10
closure()
// Stampa "10 10".
```

Se il tipo del valore dell'espressione è una classe, puoi contrassegnare l'espressione in una lista di cattura con `weak` o `unowned` per catturare un riferimento weak o unowned al valore dell'espressione.

```swift
myFunction { print(self.title) }                    // cattura forte implicita
myFunction { [self] in print(self.title) }          // cattura forte esplicita
myFunction { [weak self] in print(self!.title) }    // cattura weak
myFunction { [unowned self] in print(self.title) }  // cattura unowned
```

Puoi anche vincolare un'espressione arbitraria a un valore con nome in una lista di cattura. L'espressione viene valutata quando la closure viene creata, e il valore viene catturato con la forza specificata. Per esempio:

```swift
// Cattura weak di "self.parent" come "parent".
myFunction { [weak parent = self.parent] in print(parent!.title) }
```

Per maggiori informazioni ed esempi sulle espressioni closure, vedi [Espressioni closure](/guida-al-linguaggio/closure.md#espressioni-closure). Per maggiori informazioni ed esempi sulle liste di cattura, vedi [Risolvere i cicli di riferimenti forti per le closure](/guida-al-linguaggio/conteggio-automatico-dei-riferimenti.md#risolvere-i-cicli-di-riferimenti-forti-per-le-closure).

{% hint style="info" %}
**Grammatica di un'espressione closure:**

*closure-expression* → **`{`** *attributes?* *closure-signature?* *statements?* **`}`**

*closure-signature* → *capture-list?* *closure-parameter-clause* **`async`***?* *throws-clause?* *function-result?* **`in`**\
*closure-signature* → *capture-list* **`in`**

*closure-parameter-clause* → **`(`** **`)`** | **`(`** *closure-parameter-list* **`,`***?* **`)`** | *identifier-list*\
*closure-parameter-list* → *closure-parameter* | *closure-parameter* **`,`** *closure-parameter-list*\
*closure-parameter* → *closure-parameter-name* *type-annotation?*\
*closure-parameter* → *closure-parameter-name* *type-annotation* **`...`**\
*closure-parameter-name* → *identifier*

*capture-list* → **`[`** *capture-list-items* **`,`***?* **`]`**\
*capture-list-items* → *capture-list-item* | *capture-list-item* **`,`** *capture-list-items*\
*capture-list-item* → *capture-specifier?* *identifier*\
*capture-list-item* → *capture-specifier?* *identifier* **`=`** *expression*\
*capture-list-item* → *capture-specifier?* *self-expression*\
*capture-specifier* → **`weak`** | **`unowned`** | **`unowned(safe)`** | **`unowned(unsafe)`**
{% endhint %}

### Espressione membro implicita <a href="#espressione-membro-implicita" id="espressione-membro-implicita"></a>

Un'*espressione membro implicita* è un modo abbreviato per accedere a un membro di un tipo, come un caso di un'enumerazione o un metodo di tipo, in un contesto in cui l'inferenza di tipo può determinare il tipo implicito. Ha la forma seguente:

```swift
.<#member name#>
```

Per esempio:

```swift
var x = MyEnumeration.someValue
x = .anotherValue
```

Se il tipo inferito è un opzionale, puoi usare anche un membro del tipo non opzionale in un'espressione membro implicita.

```swift
var someOptional: MyEnumeration? = .someValue
```

Le espressioni membro implicite possono essere seguite da un operatore postfisso o da un'altra sintassi postfissa elencata in [Espressioni postfisse](/riferimento-del-linguaggio/espressioni.md#espressioni-postfisse). Questa è chiamata *espressione membro implicita concatenata*. Sebbene sia comune che tutte le espressioni postfisse concatenate abbiano lo stesso tipo, l'unico requisito è che l'intera espressione membro implicita concatenata sia convertibile nel tipo implicato dal suo contesto. Nello specifico, se il tipo implicito è un opzionale puoi usare un valore del tipo non opzionale, e se il tipo implicito è un tipo classe puoi usare un valore di una delle sue sottoclassi. Per esempio:

```swift
class SomeClass {
    static var shared = SomeClass()
    static var sharedSubclass = SomeSubclass()
    var a = AnotherClass()
}
class SomeSubclass: SomeClass { }
class AnotherClass {
    static var s = SomeClass()
    func f() -> SomeClass { return AnotherClass.s }
}
let x: SomeClass = .shared.a.f()
let y: SomeClass? = .shared
let z: SomeClass = .sharedSubclass
```

Nel codice qui sopra, il tipo di `x` corrisponde esattamente al tipo implicato dal suo contesto, il tipo di `y` è convertibile da `SomeClass` a `SomeClass?`, e il tipo di `z` è convertibile da `SomeSubclass` a `SomeClass`.

{% hint style="info" %}
**Grammatica di un'espressione membro implicita:**

*implicit-member-expression* → **`.`** *identifier*\
*implicit-member-expression* → **`.`** *identifier* **`.`** *postfix-expression*
{% endhint %}

### Espressione tra parentesi <a href="#espressione-tra-parentesi" id="espressione-tra-parentesi"></a>

Un'*espressione tra parentesi* è costituita da un'espressione racchiusa tra parentesi tonde. Puoi usare le parentesi per specificare la precedenza delle operazioni raggruppando esplicitamente le espressioni. Le parentesi di raggruppamento non cambiano il tipo di un'espressione — per esempio, il tipo di `(1)` è semplicemente `Int`.

{% hint style="info" %}
**Grammatica di un'espressione tra parentesi:**

*parenthesized-expression* → **`(`** *expression* **`)`**
{% endhint %}

### Espressione tupla <a href="#espressione-tupla" id="espressione-tupla"></a>

Un'*espressione tupla* è costituita da un elenco di espressioni separate da virgole racchiuso tra parentesi tonde. Ogni espressione può essere preceduta da un identificatore facoltativo, separato da due punti (`:`). Ha la forma seguente:

```swift
(<#identifier 1#>: <#expression 1#>, <#identifier 2#>: <#expression 2#>, <#...#>)
```

Ogni identificatore in un'espressione tupla deve essere univoco all'interno dell'ambito dell'espressione tupla. In un'espressione tupla annidata, gli identificatori allo stesso livello di annidamento devono essere univoci. Per esempio, `(a: 10, a: 20)` non è valida perché l'etichetta `a` compare due volte allo stesso livello. Tuttavia, `(a: 10, b: (a: 1, x: 2))` è valida — sebbene `a` compaia due volte, compare una volta nella tupla esterna e una volta nella tupla interna.

Un'espressione tupla può contenere zero espressioni, oppure può contenere due o più espressioni. Una singola espressione tra parentesi è un'espressione tra parentesi.

{% hint style="info" %}
**Nota:** Sia un'espressione tupla vuota sia un tipo tupla vuoto si scrivono `()` in Swift. Poiché `Void` è un alias di tipo per `()`, puoi usarlo per scrivere un tipo tupla vuoto. Tuttavia, come tutti gli alias di tipo, `Void` è sempre un tipo — non puoi usarlo per scrivere un'espressione tupla vuota.
{% endhint %}

L'ultima espressione in una tupla può essere seguita da una virgola facoltativa.

{% hint style="info" %}
**Grammatica di un'espressione tupla:**

*tuple-expression* → **`(`** **`)`** | **`(`** *tuple-element* **`,`** *tuple-element-list* **`,`***?* **`)`**\
*tuple-element-list* → *tuple-element* | *tuple-element* **`,`** *tuple-element-list*\
*tuple-element* → *expression* | *identifier* **`:`** *expression*
{% endhint %}

### Espressione wildcard <a href="#espressione-wildcard" id="espressione-wildcard"></a>

Un'*espressione wildcard* è usata per ignorare esplicitamente un valore durante un'assegnazione. Per esempio, nell'assegnazione seguente 10 viene assegnato a `x` e 20 viene ignorato:

```swift
(x, _) = (10, 20)
// x vale 10, e 20 viene ignorato
```

{% hint style="info" %}
**Grammatica di un'espressione wildcard:**

*wildcard-expression* → **`_`**
{% endhint %}

### Espressione di espansione di macro <a href="#espressione-di-espansione-di-macro" id="espressione-di-espansione-di-macro"></a>

Un'*espressione di espansione di macro* è costituita dal nome di una macro seguito da un elenco, separato da virgole e racchiuso tra parentesi, degli argomenti della macro. La macro viene espansa in fase di compilazione. Le espressioni di espansione di macro hanno la forma seguente:

```swift
<#macro name#>(<#macro argument 1#>, <#macro argument 2#>)
```

Un'espressione di espansione di macro omette le parentesi dopo il nome della macro se la macro non accetta argomenti.

Un'espressione di espansione di macro può comparire come valore predefinito di un parametro. Quando sono usate come valore predefinito del parametro di una funzione o di un metodo, le macro vengono valutate usando la posizione nel codice sorgente del punto di chiamata, non la posizione in cui compaiono nella definizione di una funzione. Tuttavia, quando un valore predefinito è un'espressione più ampia che contiene una macro oltre ad altro codice, quelle macro vengono valutate dove compaiono nella definizione della funzione.

```swift
func f(a: Int = #line, b: Int = (#line), c: Int = 100 + #line) {
    print(a, b, c)
}
f()  // Stampa "4 1 101"
```

Nella funzione qui sopra, il valore predefinito di `a` è una singola espressione di macro, quindi quella macro viene valutata usando la posizione nel codice sorgente in cui viene chiamata `f(a:b:c:)`. Al contrario, i valori di `b` e `c` sono espressioni che contengono una macro — le macro in quelle espressioni vengono valutate usando la posizione nel codice sorgente in cui è definita `f(a:b:c:)`.

Quando usi una macro come valore predefinito, viene sottoposta al controllo dei tipi senza espandere la macro, per verificare i requisiti seguenti:

* Il livello di accesso della macro è uguale o meno restrittivo di quello della funzione che la usa.
* La macro non accetta argomenti, oppure i suoi argomenti sono letterali senza interpolazione di stringhe.
* Il tipo di ritorno della macro corrisponde al tipo del parametro.

Usi le espressioni di macro per chiamare le macro freestanding. Per chiamare una macro attached, usa la sintassi degli attributi personalizzati descritta in [Attributi](/riferimento-del-linguaggio/attributi.md). Sia le macro freestanding sia quelle attached si espandono come segue:

1. Swift analizza il codice sorgente per produrre un albero sintattico astratto (AST).
2. L'implementazione della macro riceve in input nodi dell'AST ed esegue le trasformazioni richieste da quella macro.
3. I nodi dell'AST trasformati prodotti dall'implementazione della macro vengono aggiunti all'AST originale.

L'espansione di ciascuna macro è indipendente e autonoma. Tuttavia, come ottimizzazione delle prestazioni, Swift potrebbe avviare un processo esterno che implementa la macro e riutilizzare lo stesso processo per espandere più macro. Quando implementi una macro, quel codice non deve dipendere da quali macro il tuo codice ha espanso in precedenza, né da qualsiasi altro stato esterno come l'ora corrente.

Per le macro annidate e per le macro attached che hanno più ruoli, il processo di espansione si ripete. Le espressioni di espansione di macro annidate si espandono dall'esterno verso l'interno. Per esempio, nel codice seguente `outerMacro(_:)` si espande per prima e la chiamata non espansa a `innerMacro(_:)` compare nell'albero sintattico astratto che `outerMacro(_:)` riceve in input.

```swift
#outerMacro(12, #innerMacro(34), "some text")
```

Una macro attached che ha più ruoli si espande una volta per ciascun ruolo. Ogni espansione riceve in input lo stesso AST originale. Swift forma l'espansione complessiva raccogliendo tutti i nodi dell'AST generati e collocandoli nelle posizioni corrispondenti dell'AST.

Per una panoramica delle macro in Swift, vedi [Macro](/guida-al-linguaggio/macro.md).

{% hint style="info" %}
**Grammatica di un'espressione di espansione di macro:**

*macro-expansion-expression* → **`#`** *identifier* *generic-argument-clause?* *function-call-argument-clause?* *trailing-closures?*
{% endhint %}

### Espressione key-path <a href="#espressione-key-path" id="espressione-key-path"></a>

Un'*espressione key-path* fa riferimento a una proprietà o a un subscript di un tipo. Usi le espressioni key-path in attività di programmazione dinamica, come il key-value observing. Hanno la forma seguente:

```swift
\<#type name#>.<#path#>
```

Il *type name* (nome del tipo) è il nome di un tipo concreto, inclusi eventuali parametri generici, come `String`, `[Int]` o `Set<Int>`.

Il *path* (percorso) è costituito da nomi di proprietà, subscript, espressioni di optional chaining ed espressioni di unwrapping forzato. Ciascuno di questi componenti del key path può essere ripetuto tutte le volte necessarie, in qualsiasi ordine.

In fase di compilazione, un'espressione key-path viene sostituita da un'istanza della classe [`KeyPath`](https://developer.apple.com/documentation/swift/keypath).

Per accedere a un valore usando un key path, passa il key path al subscript `subscript(keyPath:)`, disponibile su tutti i tipi. Per esempio:

```swift
struct SomeStructure {
    var someValue: Int
}

let s = SomeStructure(someValue: 12)
let pathToProperty = \SomeStructure.someValue

let value = s[keyPath: pathToProperty]
// value vale 12
```

Il *type name* può essere omesso nei contesti in cui l'inferenza di tipo può determinare il tipo implicito. Il codice seguente usa `\.someProperty` invece di `\SomeClass.someProperty`:

```swift
class SomeClass: NSObject {
    @objc dynamic var someProperty: Int
    init(someProperty: Int) {
        self.someProperty = someProperty
    }
}

let c = SomeClass(someProperty: 10)
c.observe(\.someProperty) { object, change in
    // ...
}
```

Il *path* può fare riferimento a `self` per creare il key path identità (`\.self`). Il key path identità fa riferimento a un'intera istanza, quindi puoi usarlo per accedere a tutti i dati memorizzati in una variabile e modificarli in un unico passaggio. Per esempio:

```swift
var compoundValue = (a: 1, b: 2)
// Equivale a compoundValue = (a: 10, b: 20)
compoundValue[keyPath: \.self] = (a: 10, b: 20)
```

Il *path* può contenere più nomi di proprietà, separati da punti, per fare riferimento a una proprietà del valore di una proprietà. Questo codice usa l'espressione key path `\OuterStructure.outer.someValue` per accedere alla proprietà `someValue` della proprietà `outer` del tipo `OuterStructure`:

```swift
struct OuterStructure {
    var outer: SomeStructure
    init(someValue: Int) {
        self.outer = SomeStructure(someValue: someValue)
    }
}

let nested = OuterStructure(someValue: 24)
let nestedKeyPath = \OuterStructure.outer.someValue

let nestedValue = nested[keyPath: nestedKeyPath]
// nestedValue vale 24
```

Il *path* può includere subscript usando le parentesi quadre, purché il tipo del parametro del subscript sia conforme al protocollo `Hashable`. Questo esempio usa un subscript in un key path per accedere al secondo elemento di un array:

```swift
let greetings = ["hello", "hola", "bonjour", "안녕"]
let myGreeting = greetings[keyPath: \[String].[1]]
// myGreeting vale 'hola'
```

Il valore usato in un subscript può essere un valore con nome o un letterale. I valori vengono catturati nei key path usando la semantica di valore. Il codice seguente usa la variabile `index` sia in un'espressione key-path sia in una closure per accedere al terzo elemento dell'array `greetings`. Quando `index` viene modificata, l'espressione key-path fa ancora riferimento al terzo elemento, mentre la closure usa il nuovo indice.

```swift
var index = 2
let path = \[String].[index]
let fn: ([String]) -> String = { strings in strings[index] }

print(greetings[keyPath: path])
// Stampa "bonjour".
print(fn(greetings))
// Stampa "bonjour".

// Impostare 'index' a un nuovo valore non influisce su 'path'
index += 1
print(greetings[keyPath: path])
// Stampa "bonjour".

// Poiché 'fn' cattura 'index', usa il nuovo valore
print(fn(greetings))
// Stampa "안녕".
```

Il *path* può usare l'optional chaining e l'unwrapping forzato. Questo codice usa l'optional chaining in un key path per accedere a una proprietà di una stringa opzionale:

```swift
let firstGreeting: String? = greetings.first
print(firstGreeting?.count as Any)
// Stampa "Optional(5)".

// Fa la stessa cosa usando un key path.
let count = greetings[keyPath: \[String].first?.count]
print(count as Any)
// Stampa "Optional(5)".
```

Puoi combinare liberamente i componenti dei key path per accedere a valori profondamente annidati all'interno di un tipo. Il codice seguente accede a diversi valori e proprietà di un dizionario di array usando espressioni key-path che combinano questi componenti.

```swift
let interestingNumbers = ["prime": [2, 3, 5, 7, 11, 13, 17],
                          "triangular": [1, 3, 6, 10, 15, 21, 28],
                          "hexagonal": [1, 6, 15, 28, 45, 66, 91]]
print(interestingNumbers[keyPath: \[String: [Int]].["prime"]] as Any)
// Stampa "Optional([2, 3, 5, 7, 11, 13, 17])".
print(interestingNumbers[keyPath: \[String: [Int]].["prime"]![0]])
// Stampa "2".
print(interestingNumbers[keyPath: \[String: [Int]].["hexagonal"]!.count])
// Stampa "7".
print(interestingNumbers[keyPath: \[String: [Int]].["hexagonal"]!.count.bitWidth])
// Stampa "64".
```

Puoi usare un'espressione key path nei contesti in cui normalmente forniresti una funzione o una closure. Nello specifico, puoi usare un'espressione key path il cui tipo radice è `SomeType` e il cui percorso produce un valore di tipo `Value`, al posto di una funzione o di una closure di tipo `(SomeType) -> Value`.

```swift
struct Task {
    var description: String
    var completed: Bool
}
var toDoList = [
    Task(description: "Practice ping-pong.", completed: false),
    Task(description: "Buy a pirate costume.", completed: true),
    Task(description: "Visit Boston in the Fall.", completed: false),
]

// Entrambi gli approcci seguenti sono equivalenti.
let descriptions = toDoList.filter(\.completed).map(\.description)
let descriptions2 = toDoList.filter { $0.completed }.map { $0.description }
```

Gli eventuali effetti collaterali di un'espressione key path vengono valutati solo nel punto in cui l'espressione viene valutata. Per esempio, se esegui una chiamata di funzione all'interno di un subscript in un'espressione key path, la funzione viene chiamata una sola volta come parte della valutazione dell'espressione, non ogni volta che il key path viene usato.

```swift
func makeIndex() -> Int {
    print("Made an index")
    return 0
}
// La riga seguente chiama makeIndex().
let taskKeyPath = \[Task][makeIndex()]
// Stampa "Made an index".

// Usare taskKeyPath non chiama di nuovo makeIndex().
let someTask = toDoList[keyPath: taskKeyPath]
```

Per maggiori informazioni sull'uso dei key path nel codice che interagisce con le API Objective-C, vedi [Using Objective-C Runtime Features in Swift](https://developer.apple.com/documentation/swift/using_objective_c_runtime_features_in_swift). Per informazioni sul key-value coding e sul key-value observing, vedi [Key-Value Coding Programming Guide](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/KeyValueCoding/index.html#//apple_ref/doc/uid/10000107i) e [Key-Value Observing Programming Guide](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html#//apple_ref/doc/uid/10000177i).

{% hint style="info" %}
**Grammatica di un'espressione key-path:**

*key-path-expression* → **`\`** *type?* **`.`** *key-path-components*\
*key-path-components* → *key-path-component* | *key-path-component* **`.`** *key-path-components*\
*key-path-component* → *identifier* *key-path-postfixes?* | *key-path-postfixes*

*key-path-postfixes* → *key-path-postfix* *key-path-postfixes?*\
*key-path-postfix* → **`?`** | **`!`** | **`self`** | **`[`** *function-call-argument-list* **`]`**
{% endhint %}

### Espressione selector <a href="#espressione-selector" id="espressione-selector"></a>

Un'espressione selector ti permette di accedere al selettore usato per fare riferimento a un metodo o al getter o al setter di una proprietà in Objective-C. Ha la forma seguente:

```swift
#selector(<#method name#>)
#selector(getter: <#property name#>)
#selector(setter: <#property name#>)
```

Il *method name* (nome del metodo) e il *property name* (nome della proprietà) devono essere un riferimento a un metodo o a una proprietà disponibile nel runtime di Objective-C. Il valore di un'espressione selector è un'istanza del tipo `Selector`. Per esempio:

```swift
class SomeClass: NSObject {
    @objc let property: String

    @objc(doSomethingWithInt:)
    func doSomething(_ x: Int) { }

    init(property: String) {
        self.property = property
    }
}
let selectorForMethod = #selector(SomeClass.doSomething(_:))
let selectorForPropertyGetter = #selector(getter: SomeClass.property)
```

Quando crei un selettore per il getter di una proprietà, il *property name* può essere un riferimento a una proprietà variabile o costante. Al contrario, quando crei un selettore per il setter di una proprietà, il *property name* deve essere un riferimento esclusivamente a una proprietà variabile.

Il *method name* può contenere parentesi per il raggruppamento, così come l'operatore `as` per disambiguare tra metodi che condividono un nome ma hanno firme di tipo diverse. Per esempio:

```swift
extension SomeClass {
    @objc(doSomethingWithString:)
    func doSomething(_ x: String) { }
}
let anotherSelector = #selector(SomeClass.doSomething(_:) as (SomeClass) -> (String) -> Void)
```

Poiché un selettore viene creato in fase di compilazione, non in fase di esecuzione, il compilatore può verificare che un metodo o una proprietà esista e che sia esposto al runtime di Objective-C.

{% hint style="info" %}
**Nota:** Sebbene il *method name* e il *property name* siano espressioni, non vengono mai valutati.
{% endhint %}

Per maggiori informazioni sull'uso dei selettori nel codice Swift che interagisce con le API Objective-C, vedi [Using Objective-C Runtime Features in Swift](https://developer.apple.com/documentation/swift/using_objective_c_runtime_features_in_swift).

{% hint style="info" %}
**Grammatica di un'espressione selector:**

*selector-expression* → **`#selector`** **`(`** *expression* **`)`**\
*selector-expression* → **`#selector`** **`(`** **`getter:`** *expression* **`)`**\
*selector-expression* → **`#selector`** **`(`** **`setter:`** *expression* **`)`**
{% endhint %}

### Espressione stringa key-path <a href="#espressione-stringa-key-path" id="espressione-stringa-key-path"></a>

Un'espressione stringa key-path ti permette di accedere alla stringa usata per fare riferimento a una proprietà in Objective-C, da usare nelle API di key-value coding e key-value observing. Ha la forma seguente:

```swift
#keyPath(<#property name#>)
```

Il *property name* deve essere un riferimento a una proprietà disponibile nel runtime di Objective-C. In fase di compilazione, l'espressione stringa key-path viene sostituita da un letterale stringa. Per esempio:

```swift
class SomeClass: NSObject {
    @objc var someProperty: Int
    init(someProperty: Int) {
       self.someProperty = someProperty
    }
}

let c = SomeClass(someProperty: 12)
let keyPath = #keyPath(SomeClass.someProperty)

if let value = c.value(forKey: keyPath) {
    print(value)
}
// Stampa "12".
```

Quando usi un'espressione stringa key-path all'interno di una classe, puoi fare riferimento a una proprietà di quella classe scrivendo solo il nome della proprietà, senza il nome della classe.

```swift
extension SomeClass {
    func getSomeKeyPath() -> String {
        return #keyPath(someProperty)
    }
}
print(keyPath == c.getSomeKeyPath())
// Stampa "true".
```

Poiché la stringa key path viene creata in fase di compilazione, non in fase di esecuzione, il compilatore può verificare che la proprietà esista e che la proprietà sia esposta al runtime di Objective-C.

Per maggiori informazioni sull'uso dei key path nel codice Swift che interagisce con le API Objective-C, vedi [Using Objective-C Runtime Features in Swift](https://developer.apple.com/documentation/swift/using_objective_c_runtime_features_in_swift). Per informazioni sul key-value coding e sul key-value observing, vedi [Key-Value Coding Programming Guide](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/KeyValueCoding/index.html#//apple_ref/doc/uid/10000107i) e [Key-Value Observing Programming Guide](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html#//apple_ref/doc/uid/10000177i).

{% hint style="info" %}
**Nota:** Sebbene il *property name* sia un'espressione, non viene mai valutato.
{% endhint %}

{% hint style="info" %}
**Grammatica di un'espressione stringa key-path:**

*key-path-string-expression* → **`#keyPath`** **`(`** *expression* **`)`**
{% endhint %}

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

Le *espressioni postfisse* si formano applicando un operatore postfisso o un'altra sintassi postfissa a un'espressione. Sintatticamente, ogni espressione primaria è anche un'espressione postfissa.

Per informazioni sul comportamento di questi operatori, vedi [Operatori di base](/guida-al-linguaggio/operatori-di-base.md) e [Operatori avanzati](/guida-al-linguaggio/operatori-avanzati.md).

Per informazioni sugli operatori forniti dalla libreria standard di Swift, vedi [Operator Declarations](https://developer.apple.com/documentation/swift/operator_declarations).

{% hint style="info" %}
**Grammatica di un'espressione postfissa:**

*postfix-expression* → *primary-expression*\
*postfix-expression* → *postfix-expression* *postfix-operator*\
*postfix-expression* → *function-call-expression*\
*postfix-expression* → *initializer-expression*\
*postfix-expression* → *explicit-member-expression*\
*postfix-expression* → *postfix-self-expression*\
*postfix-expression* → *subscript-expression*\
*postfix-expression* → *forced-value-expression*\
*postfix-expression* → *optional-chaining-expression*
{% endhint %}

### Espressione di chiamata di funzione <a href="#espressione-di-chiamata-di-funzione" id="espressione-di-chiamata-di-funzione"></a>

Un'*espressione di chiamata di funzione* è costituita dal nome di una funzione seguito da un elenco, separato da virgole e racchiuso tra parentesi, degli argomenti della funzione. Le espressioni di chiamata di funzione hanno la forma seguente:

```swift
<#function name#>(<#argument value 1#>, <#argument value 2#>)
```

Il *function name* (nome della funzione) può essere qualsiasi espressione il cui valore sia di un tipo funzione.

Se la definizione della funzione include nomi per i suoi parametri, la chiamata di funzione deve includere i nomi prima dei valori degli argomenti, separati da due punti (`:`). Questo tipo di espressione di chiamata di funzione ha la forma seguente:

```swift
<#function name#>(<#argument name 1#>: <#argument value 1#>, <#argument name 2#>: <#argument value 2#>)
```

L'ultimo argomento tra parentesi può essere seguito da una virgola facoltativa.

Un'espressione di chiamata di funzione può includere trailing closure sotto forma di espressioni closure subito dopo la parentesi di chiusura. Le trailing closure sono considerate argomenti della funzione, aggiunti dopo l'ultimo argomento tra parentesi. La prima espressione closure è priva di etichetta; le eventuali espressioni closure aggiuntive sono precedute dalle loro etichette dell'argomento. L'esempio seguente mostra la versione equivalente di chiamate di funzione che usano e non usano la sintassi delle trailing closure:

```swift
// someFunction accetta come argomenti un intero e una closure
someFunction(x: x, f: { $0 == 13 })
someFunction(x: x) { $0 == 13 }

// anotherFunction accetta come argomenti un intero e due closure
anotherFunction(x: x, f: { $0 == 13 }, g: { print(99) })
anotherFunction(x: x) { $0 == 13 } g: { print(99) }
```

Se la trailing closure è l'unico argomento della funzione, puoi omettere le parentesi.

```swift
// someMethod accetta una closure come unico argomento
myData.someMethod() { $0 == 13 }
myData.someMethod { $0 == 13 }
```

Per includere le trailing closure negli argomenti, il compilatore esamina i parametri della funzione da sinistra a destra come segue:

| Trailing closure | Parametro             | Azione                                                                                                                                                              |
| ---------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Con etichetta    | Con etichetta         | Se le etichette sono uguali, la closure corrisponde al parametro; altrimenti, il parametro viene saltato.                                                           |
| Con etichetta    | Senza etichetta       | Il parametro viene saltato.                                                                                                                                         |
| Senza etichetta  | Con o senza etichetta | Se il parametro somiglia strutturalmente a un tipo funzione, come definito di seguito, la closure corrisponde al parametro; altrimenti, il parametro viene saltato. |

La trailing closure viene passata come argomento del parametro a cui corrisponde. I parametri saltati durante il processo di scansione non ricevono alcun argomento — per esempio, possono usare un parametro predefinito. Dopo aver trovato una corrispondenza, la scansione prosegue con la trailing closure successiva e il parametro successivo. Al termine del processo di corrispondenza, tutte le trailing closure devono avere una corrispondenza.

Un parametro *somiglia strutturalmente* a un tipo funzione se il parametro non è un parametro in-out e il parametro è uno dei seguenti:

* Un parametro il cui tipo è un tipo funzione, come `(Bool) -> Int`
* Un parametro autoclosure il cui tipo dell'espressione racchiusa è un tipo funzione, come `@autoclosure () -> ((Bool) -> Int)`
* Un parametro variadico il cui tipo degli elementi dell'array è un tipo funzione, come `((Bool) -> Int)...`
* Un parametro il cui tipo è racchiuso in uno o più livelli di opzionale, come `Optional<(Bool) -> Int>`
* Un parametro il cui tipo combina questi tipi ammessi, come `(Optional<(Bool) -> Int>)...`

Quando una trailing closure viene fatta corrispondere a un parametro il cui tipo somiglia strutturalmente a un tipo funzione, ma non è una funzione, la closure viene racchiusa secondo necessità. Per esempio, se il tipo del parametro è un tipo opzionale, la closure viene racchiusa automaticamente in `Optional`.

Per facilitare la migrazione del codice dalle versioni di Swift precedenti alla 5.3 — che eseguivano questa corrispondenza da destra a sinistra — il compilatore verifica sia l'ordinamento da sinistra a destra sia quello da destra a sinistra. Se le due direzioni di scansione producono risultati diversi, viene usato il vecchio ordinamento da destra a sinistra e il compilatore genera un avviso. Una versione futura di Swift userà sempre l'ordinamento da sinistra a destra.

```swift
typealias Callback = (Int) -> Int
func someFunction(firstClosure: Callback? = nil,
                secondClosure: Callback? = nil) {
    let first = firstClosure?(10)
    let second = secondClosure?(20)
    print(first ?? "-", second ?? "-")
}

someFunction()  // Stampa "- -"
someFunction { return $0 + 100 }  // Ambiguo
someFunction { return $0 } secondClosure: { return $0 }  // Stampa "10 20"
```

Nell'esempio qui sopra, la chiamata di funzione contrassegnata come "Ambiguo" stampa "- 120" e produce un avviso del compilatore in Swift 5.3. Una versione futura di Swift stamperà “110 -”.

Un tipo classe, struttura o enumerazione può abilitare lo zucchero sintattico per la sintassi di chiamata di funzione dichiarando uno tra diversi metodi, come descritto in [Metodi con nomi speciali](/riferimento-del-linguaggio/dichiarazioni.md#metodi-con-nomi-speciali).

#### Conversione implicita in un tipo puntatore <a href="#conversione-implicita-in-un-tipo-puntatore" id="conversione-implicita-in-un-tipo-puntatore"></a>

In un'espressione di chiamata di funzione, se l'argomento e il parametro hanno un tipo diverso, il compilatore cerca di far corrispondere i loro tipi applicando una delle conversioni implicite dell'elenco seguente:

* `inout SomeType` può diventare `UnsafePointer<SomeType>` o `UnsafeMutablePointer<SomeType>`
* `inout Array<SomeType>` può diventare `UnsafePointer<SomeType>` o `UnsafeMutablePointer<SomeType>`
* `Array<SomeType>` può diventare `UnsafePointer<SomeType>`
* `String` può diventare `UnsafePointer<CChar>`

Le due chiamate di funzione seguenti sono equivalenti:

```swift
func unsafeFunction(pointer: UnsafePointer<Int>) {
    // ...
}
var myNumber = 1234

unsafeFunction(pointer: &myNumber)
withUnsafePointer(to: myNumber) { unsafeFunction(pointer: $0) }
```

Un puntatore creato da queste conversioni implicite è valido solo per la durata della chiamata di funzione. Per evitare comportamenti indefiniti, assicurati che il tuo codice non conservi mai il puntatore dopo la fine della chiamata di funzione.

{% hint style="info" %}
**Nota:** Quando converte implicitamente un array in un puntatore unsafe, Swift garantisce che la memoria dell'array sia contigua convertendo o copiando l'array secondo necessità. Per esempio, puoi usare questa sintassi con un array di cui è stato fatto il bridging ad `Array` da una sottoclasse di `NSArray` che non fornisce alcun contratto API sulla propria memoria. Se devi garantire che la memoria dell'array sia già contigua, così che la conversione implicita non debba mai svolgere questo lavoro, usa `ContiguousArray` invece di `Array`.
{% endhint %}

Usare `&` invece di una funzione esplicita come `withUnsafePointer(to:)` può contribuire a rendere più leggibili le chiamate a funzioni C di basso livello, specialmente quando la funzione accetta diversi argomenti puntatore. Tuttavia, quando chiami funzioni da altro codice Swift, evita di usare `&` al posto di usare esplicitamente le API unsafe.

{% hint style="info" %}
**Grammatica di un'espressione di chiamata di funzione:**

*function-call-expression* → *postfix-expression* *function-call-argument-clause*\
*function-call-expression* → *postfix-expression* *function-call-argument-clause?* *trailing-closures*

*function-call-argument-clause* → **`(`** **`)`** | **`(`** *function-call-argument-list* **`,`***?* **`)`**\
*function-call-argument-list* → *function-call-argument* | *function-call-argument* **`,`** *function-call-argument-list*\
*function-call-argument* → *expression* | *identifier* **`:`** *expression*\
*function-call-argument* → *operator* | *identifier* **`:`** *operator*

*trailing-closures* → *closure-expression* *labeled-trailing-closures?*\
*labeled-trailing-closures* → *labeled-trailing-closure* *labeled-trailing-closures?*\
*labeled-trailing-closure* → *identifier* **`:`** *closure-expression*
{% endhint %}

### Espressione di inizializzazione <a href="#espressione-di-inizializzazione" id="espressione-di-inizializzazione"></a>

Un'*espressione di inizializzazione* fornisce accesso all'inizializzatore di un tipo. Ha la forma seguente:

```swift
<#expression#>.init(<#initializer arguments#>)
```

Usi l'espressione di inizializzazione in un'espressione di chiamata di funzione per inizializzare una nuova istanza di un tipo. Usi un'espressione di inizializzazione anche per delegare all'inizializzatore di una superclasse.

```swift
class SomeSubClass: SomeSuperClass {
    override init() {
        // qui va l'inizializzazione della sottoclasse
        super.init()
    }
}
```

Come una funzione, un inizializzatore può essere usato come valore. Per esempio:

```swift
// L'annotazione di tipo è necessaria perché String ha più inizializzatori.
let initializer: (Int) -> String = String.init
let oneTwoThree = [1, 2, 3].map(initializer).reduce("", +)
print(oneTwoThree)
// Stampa "123".
```

Se specifichi un tipo per nome, puoi accedere all'inizializzatore del tipo senza usare un'espressione di inizializzazione. In tutti gli altri casi, devi usare un'espressione di inizializzazione.

```swift
let s1 = SomeType.init(data: 3)  // Valido
let s2 = SomeType(data: 1)       // Anche questo valido

let s3 = type(of: someValue).init(data: 7)  // Valido
let s4 = type(of: someValue)(data: 5)       // Errore
```

{% hint style="info" %}
**Grammatica di un'espressione di inizializzazione:**

*initializer-expression* → *postfix-expression* **`.`** **`init`**\
*initializer-expression* → *postfix-expression* **`.`** **`init`** **`(`** *argument-names* **`)`**
{% endhint %}

### Espressione membro esplicita <a href="#espressione-membro-esplicita" id="espressione-membro-esplicita"></a>

Un'*espressione membro esplicita* consente l'accesso ai membri di un tipo con nome, di una tupla o di un modulo. È costituita da un punto (`.`) tra l'elemento e l'identificatore del suo membro.

```swift
<#expression#>.<#member name#>
```

I membri di un tipo con nome ricevono il loro nome come parte della dichiarazione o dell'estensione del tipo. Per esempio:

```swift
class SomeClass {
    var someProperty = 42
}
let c = SomeClass()
let y = c.someProperty  // Accesso a un membro
```

I membri di una tupla sono nominati implicitamente usando numeri interi nell'ordine in cui compaiono, a partire da zero. Per esempio:

```swift
var t = (10, 20, 30)
t.0 = t.1
// Ora t vale (20, 20, 30)
```

I membri di un modulo accedono alle dichiarazioni di primo livello di quel modulo.

I tipi dichiarati con l'attributo `dynamicMemberLookup` includono membri che vengono cercati in fase di esecuzione, come descritto in [Attributi](/riferimento-del-linguaggio/attributi.md).

Per distinguere tra metodi o inizializzatori i cui nomi differiscono solo per i nomi dei loro argomenti, includi i nomi degli argomenti tra parentesi, con ciascun nome di argomento seguito da due punti (`:`). Scrivi un trattino basso (`_`) per un argomento senza nome. Per distinguere tra metodi in overload, usa un'annotazione di tipo. Per esempio:

```swift
class SomeClass {
    func someMethod(x: Int, y: Int) {}
    func someMethod(x: Int, z: Int) {}
    func overloadedMethod(x: Int, y: Int) {}
    func overloadedMethod(x: Int, y: Bool) {}
}
let instance = SomeClass()

let a = instance.someMethod              // Ambiguo
let b = instance.someMethod(x:y:)        // Non ambiguo

let d = instance.overloadedMethod        // Ambiguo
let d = instance.overloadedMethod(x:y:)  // Ancora ambiguo
let d: (Int, Bool) -> Void  = instance.overloadedMethod(x:y:)  // Non ambiguo
```

Se un punto compare all'inizio di una riga, viene interpretato come parte di un'espressione membro esplicita, non come un'espressione membro implicita. Per esempio, il listato seguente mostra chiamate di metodo concatenate suddivise su più righe:

```swift
let x = [10, 3, 20, 15, 4]
    .sorted()
    .filter { $0 > 5 }
    .map { $0 * 100 }
```

Puoi combinare questa sintassi concatenata su più righe con le istruzioni di controllo del compilatore per controllare quando viene chiamato ciascun metodo. Per esempio, il codice seguente usa una regola di filtraggio diversa su iOS:

```swift
let numbers = [10, 20, 33, 43, 50]
#if os(iOS)
    .filter { $0 < 40 }
#else
    .filter { $0 > 25 }
#endif
```

Tra `#if`, `#endif` e le altre direttive di compilazione, il blocco di compilazione condizionale può contenere un'espressione membro implicita seguita da zero o più postfissi, per formare un'espressione postfissa. Può anche contenere un altro blocco di compilazione condizionale, o una combinazione di queste espressioni e blocchi.

Puoi usare questa sintassi ovunque tu possa scrivere un'espressione membro esplicita, non solo nel codice di primo livello.

Nel blocco di compilazione condizionale, il ramo della direttiva di compilazione `#if` deve contenere almeno un'espressione. Gli altri rami possono essere vuoti.

{% hint style="info" %}
**Grammatica di un'espressione membro esplicita:**

*explicit-member-expression* → *postfix-expression* **`.`** *decimal-digits*\
*explicit-member-expression* → *postfix-expression* **`.`** *identifier* *generic-argument-clause?*\
*explicit-member-expression* → *postfix-expression* **`.`** *identifier* **`(`** *argument-names* **`)`**\
*explicit-member-expression* → *postfix-expression* *conditional-compilation-block*

*argument-names* → *argument-name* *argument-names?*\
*argument-name* → *identifier* **`:`**
{% endhint %}

### Espressione self postfissa <a href="#espressione-self-postfissa" id="espressione-self-postfissa"></a>

Un'espressione `self` postfissa è costituita da un'espressione o dal nome di un tipo, seguiti immediatamente da `.self`. Ha le forme seguenti:

```swift
<#expression#>.self
<#type#>.self
```

La prima forma restituisce il valore dell'*expression*. Per esempio, `x.self` restituisce `x`.

La seconda forma restituisce il valore del *type*. Usa questa forma per accedere a un tipo come valore. Per esempio, poiché `SomeClass.self` restituisce il tipo `SomeClass` stesso, puoi passarlo a una funzione o a un metodo che accetta un argomento a livello di tipo.

{% hint style="info" %}
**Grammatica di un'espressione self postfissa:**

*postfix-self-expression* → *postfix-expression* **`.`** **`self`**
{% endhint %}

### Espressione subscript <a href="#espressione-subscript" id="espressione-subscript"></a>

Un'*espressione subscript* fornisce l'accesso tramite subscript usando il getter e il setter della dichiarazione di subscript corrispondente. Ha la forma seguente:

```swift
<#expression#>[<#index expressions#>]
```

Per valutare il valore di un'espressione subscript, viene chiamato il getter del subscript del tipo dell'*expression* con le *index expressions* passate come parametri del subscript. Per impostarne il valore, il setter del subscript viene chiamato allo stesso modo.

Per informazioni sulle dichiarazioni di subscript, vedi [Dichiarazione di subscript di un protocollo](/riferimento-del-linguaggio/dichiarazioni.md#dichiarazione-di-subscript-di-un-protocollo).

{% hint style="info" %}
**Grammatica di un'espressione subscript:**

*subscript-expression* → *postfix-expression* **`[`** *function-call-argument-list* **`]`**
{% endhint %}

### Espressione a valore forzato <a href="#espressione-a-valore-forzato" id="espressione-a-valore-forzato"></a>

Un'*espressione a valore forzato* esegue l'unwrapping di un valore opzionale che sei certo non sia `nil`. Ha la forma seguente:

```swift
<#expression#>!
```

Se il valore dell'*expression* non è `nil`, viene eseguito l'unwrapping del valore opzionale, che viene restituito con il tipo non opzionale corrispondente. Altrimenti, viene generato un errore in fase di esecuzione.

Il valore di un'espressione a valore forzato su cui è stato eseguito l'unwrapping può essere modificato, sia mutando il valore stesso, sia assegnando un valore a uno dei membri del valore. Per esempio:

```swift
var x: Int? = 0
x! += 1
// x ora vale 1

var someDictionary = ["a": [1, 2, 3], "b": [10, 20]]
someDictionary["a"]![0] = 100
// someDictionary ora vale ["a": [100, 2, 3], "b": [10, 20]]
```

{% hint style="info" %}
**Grammatica di un'espressione a valore forzato:**

*forced-value-expression* → *postfix-expression* **`!`**
{% endhint %}

### Espressione di optional chaining <a href="#espressione-di-optional-chaining" id="espressione-di-optional-chaining"></a>

Un'*espressione di optional chaining* fornisce una sintassi semplificata per usare valori opzionali nelle espressioni postfisse. Ha la forma seguente:

```swift
<#expression#>?
```

L'operatore postfisso `?` crea un'espressione di optional chaining a partire da un'espressione senza cambiarne il valore.

Le espressioni di optional chaining devono comparire all'interno di un'espressione postfissa, e fanno sì che l'espressione postfissa venga valutata in un modo speciale. Se il valore dell'espressione di optional chaining è `nil`, tutte le altre operazioni nell'espressione postfissa vengono ignorate e l'intera espressione postfissa restituisce `nil`. Se il valore dell'espressione di optional chaining non è `nil`, viene eseguito l'unwrapping del valore dell'espressione di optional chaining, che viene usato per valutare il resto dell'espressione postfissa. In entrambi i casi, il valore dell'espressione postfissa è comunque di un tipo opzionale.

Se un'espressione postfissa che contiene un'espressione di optional chaining è annidata all'interno di altre espressioni postfisse, solo l'espressione più esterna restituisce un tipo opzionale. Nell'esempio seguente, quando `c` non è `nil`, viene eseguito l'unwrapping del suo valore, che viene usato per valutare `.property`, il cui valore viene usato per valutare `.performAction()`. L'intera espressione `c?.property.performAction()` ha un valore di tipo opzionale.

```swift
var c: SomeClass?
var result: Bool? = c?.property.performAction()
```

L'esempio seguente mostra il comportamento dell'esempio precedente senza usare l'optional chaining.

```swift
var result: Bool?
if let unwrappedC = c {
    result = unwrappedC.property.performAction()
}
```

Il valore di un'espressione di optional chaining su cui è stato eseguito l'unwrapping può essere modificato, sia mutando il valore stesso, sia assegnando un valore a uno dei membri del valore. Se il valore dell'espressione di optional chaining è `nil`, l'espressione sul lato destro dell'operatore di assegnazione non viene valutata. Per esempio:

```swift
func someFunctionWithSideEffects() -> Int {
    return 42  // Nessun effetto collaterale reale.
}
var someDictionary = ["a": [1, 2, 3], "b": [10, 20]]

someDictionary["not here"]?[0] = someFunctionWithSideEffects()
// someFunctionWithSideEffects non viene valutata
// someDictionary vale ancora ["a": [1, 2, 3], "b": [10, 20]]

someDictionary["a"]?[0] = someFunctionWithSideEffects()
// someFunctionWithSideEffects viene valutata e restituisce 42
// someDictionary ora vale ["a": [42, 2, 3], "b": [10, 20]]
```

{% hint style="info" %}
**Grammatica di un'espressione di optional chaining:**

*optional-chaining-expression* → *postfix-expression* **`?`**
{% endhint %}
