> 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/parametri-e-argomenti-generici.md).

# Parametri e argomenti generici (Generic Parameters and Arguments)

Generalizza le dichiarazioni per astrarre dai tipi concreti.

Questo capitolo descrive i parametri e gli argomenti per tipi, funzioni e inizializzatori generici. Quando dichiari un tipo, una funzione, un subscript o un inizializzatore generico, specifichi i parametri di tipo con cui il tipo, la funzione o l'inizializzatore generico può lavorare. Questi parametri di tipo fungono da segnaposto che vengono sostituiti da effettivi argomenti di tipo concreti quando viene creata un'istanza di un tipo generico o viene chiamata una funzione o un inizializzatore generico.

Per una panoramica dei generici in Swift, vedi [Generici](/guida-al-linguaggio/generici.md).

## Clausola dei parametri generici <a href="#clausola-dei-parametri-generici" id="clausola-dei-parametri-generici"></a>

Una *clausola dei parametri generici* specifica i parametri di tipo di un tipo o di una funzione generica, insieme a eventuali vincoli e requisiti associati a tali parametri. Una clausola dei parametri generici è racchiusa tra parentesi angolari (<>) e ha la forma seguente:

```swift
<<#generic parameter list#>>
```

La *generic parameter list* (elenco dei parametri generici) è un elenco di parametri generici separati da virgole, ciascuno dei quali ha la forma seguente:

```swift
<#type parameter#>: <#constraint#>
```

Un parametro generico è costituito da un *type parameter* (parametro di tipo) seguito da un *constraint* (vincolo) opzionale. Un *parametro di tipo* è semplicemente il nome di un tipo segnaposto (per esempio, `T`, `U`, `V`, `Key`, `Value` e così via). Hai accesso ai parametri di tipo (e a qualsiasi loro tipo associato) nel resto della dichiarazione del tipo, della funzione o dell'inizializzatore, compresa la firma della funzione o dell'inizializzatore.

Il *vincolo* specifica che un parametro di tipo eredita da una specifica classe oppure è conforme a un protocollo o a una composizione di protocolli. Per esempio, nella funzione generica seguente, il parametro generico `T: Comparable` indica che qualsiasi argomento di tipo sostituito al parametro di tipo `T` deve essere conforme al protocollo `Comparable`.

```swift
func simpleMax<T: Comparable>(_ x: T, _ y: T) -> T {
    if x < y {
        return y
    }
    return x
}
```

Poiché `Int` e `Double`, per esempio, sono entrambi conformi al protocollo `Comparable`, questa funzione accetta argomenti di entrambi i tipi. Diversamente dai tipi generici, non specifichi una clausola degli argomenti generici quando usi una funzione o un inizializzatore generico. Gli argomenti di tipo vengono invece inferiti dal tipo degli argomenti passati alla funzione o all'inizializzatore.

```swift
simpleMax(17, 42) // T viene inferito come Int
simpleMax(3.14159, 2.71828) // T viene inferito come Double
```

L'ultimo parametro generico di un elenco di parametri generici può essere seguito da una virgola opzionale.

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

Un *parametro generico intero* funge da segnaposto per un valore intero anziché per un tipo. Ha la forma seguente:

```swift
let <#type parameter#>: <#type>
```

Il *type* (tipo) deve essere il tipo `Int` della libreria standard di Swift, oppure un alias di tipo o un tipo generico che si risolve in `Int`.

Il valore che fornisci per un parametro generico intero deve essere un letterale intero oppure un altro parametro generico intero del contesto generico che lo racchiude. Per esempio:

```swift
struct SomeStruct<let x: Int> { }
let a: SomeStruct<2>  // OK: letterale intero

struct AnotherStruct<let x: Int, T, each U> {
    let b: SomeStruct<x>  // OK: un altro parametro generico intero

    static let c = 42
    let d: SomeStruct<c>  // Errore: non si può usare una costante.

    let e: SomeStruct<T>  // Errore: non si può usare un parametro di tipo generico.
    let f: SomeStruct<U>  // Errore: non si può usare un parameter pack.
}
```

Il valore di un parametro generico intero di un tipo è accessibile come membro costante statico di quel tipo, con la stessa visibilità del tipo stesso. Il valore di un parametro generico intero di una funzione è accessibile come costante dall'interno della funzione. Quando vengono usate in un'espressione, queste costanti hanno tipo `Int`.

```swift
print(a.x)  // Stampa "4"
```

Il valore di un parametro generico intero può essere inferito dai tipi degli argomenti che usi quando inizializzi il tipo o chiami la funzione.

```swift
struct AnotherStruct<let y: Int> {
    var s: SomeStruct<y>
}
func someFunction<let z: Int>(s: SomeStruct<z>) {
    print(z)
}

let s1 = SomeStruct<12>()
let s2 = AnotherStruct(s: s1)  // AnotherStruct.y viene inferito come 12.
someFunction(s: s1)  // Stampa "12"
```

### Clausole where generiche <a href="#clausole-where-generiche" id="clausole-where-generiche"></a>

Puoi specificare requisiti aggiuntivi sui parametri di tipo e sui loro tipi associati includendo una clausola `where` generica subito prima della parentesi graffa di apertura del corpo di un tipo o di una funzione. Una clausola `where` generica è costituita dalla parola chiave `where`, seguita da un elenco separato da virgole di uno o più *requirements* (requisiti).

```swift
where <#requirements#>
```

I *requisiti* di una clausola `where` generica specificano che un parametro di tipo eredita da una classe oppure è conforme a un protocollo o a una composizione di protocolli. Sebbene la clausola `where` generica fornisca uno zucchero sintattico per esprimere vincoli semplici sui parametri di tipo (per esempio, `<T: Comparable>` equivale a `<T> where T: Comparable` e così via), puoi usarla per fornire vincoli più complessi sui parametri di tipo e sui loro tipi associati. Per esempio, puoi vincolare i tipi associati dei parametri di tipo a essere conformi a dei protocolli. Per esempio, `<S: Sequence> where S.Iterator.Element: Equatable` specifica che `S` è conforme al protocollo `Sequence` e che il tipo associato `S.Iterator.Element` è conforme al protocollo `Equatable`. Questo vincolo garantisce che ogni elemento della sequenza sia confrontabile per uguaglianza (equatable). I parametri generici interi non possono avere requisiti di protocollo o di superclasse.

Puoi anche specificare il requisito che due tipi siano identici, usando l'operatore `==`. Per esempio, `<S1: Sequence, S2: Sequence> where S1.Iterator.Element == S2.Iterator.Element` esprime i vincoli che `S1` e `S2` siano conformi al protocollo `Sequence` e che gli elementi di entrambe le sequenze debbano essere dello stesso tipo. Per i parametri generici interi, l'operatore `==` specifica un requisito sui loro valori. Puoi richiedere che due parametri generici interi abbiano lo stesso valore, oppure puoi richiedere uno specifico valore intero per il parametro generico intero.

Qualsiasi argomento di tipo sostituito a un parametro di tipo deve soddisfare tutti i vincoli e i requisiti imposti sul parametro di tipo.

Una clausola `where` generica può comparire come parte di una dichiarazione che include parametri di tipo, oppure come parte di una dichiarazione annidata all'interno di una dichiarazione che include parametri di tipo. La clausola `where` generica di una dichiarazione annidata può comunque riferirsi ai parametri di tipo della dichiarazione che la racchiude; tuttavia, i requisiti di quella clausola `where` si applicano solo alla dichiarazione in cui è scritta.

Se anche la dichiarazione che la racchiude ha una clausola `where`, i requisiti di entrambe le clausole vengono combinati. Nell'esempio seguente, `startsWithZero()` è disponibile solo se `Element` è conforme sia a `SomeProtocol` sia a `Numeric`.

```swift
extension Collection where Element: SomeProtocol {
    func startsWithZero() -> Bool where Element: Numeric {
        return first == .zero
    }
}
```

Puoi eseguire l'overload di una funzione o di un inizializzatore generico fornendo vincoli, requisiti o entrambi diversi sui parametri di tipo. Quando chiami una funzione o un inizializzatore generico sottoposto a overload, il compilatore usa questi vincoli per determinare quale funzione o inizializzatore sottoposto a overload invocare.

Per maggiori informazioni sulle clausole `where` generiche e per vedere un esempio di una di esse nella dichiarazione di una funzione generica, vedi [Clausole where generiche](/guida-al-linguaggio/generici.md#clausole-where-generiche).

{% hint style="info" %}
**Grammatica di una clausola dei parametri generici:**

*generic-parameter-clause* → **`<`** *generic-parameter-list* **`,`***?* **`>`**\
*generic-parameter-list* → *generic-parameter* | *generic-parameter* **`,`** *generic-parameter-list*\
*generic-parameter* → *type-name*\
*generic-parameter* → *type-name* **`:`** *type-identifier*\
*generic-parameter* → *type-name* **`:`** *protocol-composition-type*\
*generic-parameter* → **`let`** *type-name* **`:`** *type* \\

*generic-where-clause* → **`where`** *requirement-list*\
*requirement-list* → *requirement* | *requirement* **`,`** *requirement-list*\
*requirement* → *conformance-requirement* | *same-type-requirement*

*conformance-requirement* → *type-identifier* **`:`** *type-identifier*\
*conformance-requirement* → *type-identifier* **`:`** *protocol-composition-type*\
*same-type-requirement* → *type-identifier* **`==`** *type*\
*same-type-requirement* → *type-identifier* **`==`** *signed-integer-literal*
{% endhint %}

## Clausola degli argomenti generici <a href="#clausola-degli-argomenti-generici" id="clausola-degli-argomenti-generici"></a>

Una *clausola degli argomenti generici* specifica gli argomenti di tipo di un tipo generico. Una clausola degli argomenti generici è racchiusa tra parentesi angolari (<>) e ha la forma seguente:

```swift
<<#generic argument list#>>
```

La *generic argument list* (elenco degli argomenti generici) è un elenco di argomenti di tipo separati da virgole. Un *argomento di tipo* è il nome di un effettivo tipo concreto che sostituisce un corrispondente parametro di tipo nella clausola dei parametri generici di un tipo generico — oppure, per un parametro generico intero, un valore intero che sostituisce quel parametro generico intero. Il risultato è una versione specializzata di quel tipo generico. L'esempio seguente mostra una versione semplificata del tipo dizionario generico della libreria standard di Swift.

```swift
struct Dictionary<Key: Hashable, Value>: Collection, ExpressibleByDictionaryLiteral {
    /* ... */
}
```

La versione specializzata del tipo generico `Dictionary`, `Dictionary<String, Int>`, si ottiene sostituendo i parametri generici `Key: Hashable` e `Value` con gli argomenti di tipo concreti `String` e `Int`. Ogni argomento di tipo deve soddisfare tutti i vincoli del parametro generico che sostituisce, compresi eventuali requisiti aggiuntivi specificati in una clausola `where` generica. Nell'esempio qui sopra, il parametro di tipo `Key` è vincolato a essere conforme al protocollo `Hashable` e quindi anche `String` deve essere conforme al protocollo `Hashable`.

Puoi anche sostituire un parametro di tipo con un argomento di tipo che sia esso stesso una versione specializzata di un tipo generico (purché soddisfi i vincoli e i requisiti appropriati). Per esempio, puoi sostituire il parametro di tipo `Element` in `Array<Element>` con una versione specializzata di un array, `Array<Int>`, per formare un array i cui elementi sono a loro volta array di interi.

```swift
let arrayOfArrays: Array<Array<Int>> = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
```

L'ultimo argomento di tipo di un elenco di argomenti generici può essere seguito da una virgola opzionale.

Come accennato in [Clausola dei parametri generici](/riferimento-del-linguaggio/parametri-e-argomenti-generici.md#clausola-dei-parametri-generici), non usi una clausola degli argomenti generici per specificare gli argomenti di tipo di una funzione o di un inizializzatore generico.

{% hint style="info" %}
**Grammatica di una clausola degli argomenti generici:**

*generic-argument-clause* → **`<`** *generic-argument-list* **`,`***?* **`>`**\
*generic-argument-list* → *generic-argument* | *generic-argument* **`,`** *generic-argument-list*\
*generic-argument* → *type* | *signed-integer-literal*
{% endhint %}
