Closures

Le closures sono blocchi autonomi che possono essere passati a diverse funzioni e utilizzati nel codice. Le closures in Swift sono simili ai blocchi in C e Objective-C.

Le closures sono in grado di catturare e memorizzare riferimenti ad eventuali costanti e variabili nel contesto in cui sono definite. Questa prassi è nota come “chiusura” di quelle costanti e variabili, da qui il nome di “closures”.

Le funzioni globali e nidificate, come già introdotto, sono in realtà casi particolari di chiusure. Possono assumere una di queste forme:

Le funzioni globali sono chiusure che hanno un nome e non catturano alcun valore.

Le funzioni nidificate sono chiusure che hanno un nome e sono in grado di catturare i valori dalla funzione che le racchiude.

Le espressioni di chiusura di Swift hanno uno stile chiaro e pulito, grazie alle ottimizzazioni che incoraggiano a scrivere una sintassi breve ed impeccabile in tutti gli scenari di programmazione. Queste ottimizzazioni includono:

Deduzione automatica dei tipi di ritorno in base al contesto
Nomi degli argomenti ben distinti
Auto-completamento della sintassi di chiusura.


Closure Expressions

Le funzioni nidificate, come già  introdotto, sono un comodo mezzo di denominazione e definizione di blocchi indipendenti di codice come parte di una funzione più ampia. Tuttavia, a volte è utile scrivere versioni brevi di costrutti di funzione simile senza dichiararne e il nome completo. Questo è particolarmente vero quando si lavora con le funzioni che richiedono altre funzioni come argomento.

Le espressioni di chiusura sono un modo per scrivere chiusure inline in una sintassi breve e concisa. Queste espressioni forniscono diverse ottimizzazioni di sintassi per la scrittura delle closures nella loro forma più semplice, senza perdite di purezza o errori accidentali. Gli esempi seguenti illustrano espressioni di chiusura ottimizzate, ognuna delle quali esprime la stessa funzionalità in maniera più succinta.


The Sort Function

La libreria standard di Swift offre una funzione chiamata “sort”(ordina), che appunto ordina una serie di valori di tipo noto, in base all’uscita fornita da una chiusura. Una volta completato il processo di ordinamento, la funzione restituisce un nuovo array dello stesso tipo e dimensione di quello vecchio, con i suoi elementi ordinati in modo corretto.

La  closures utilizzata nell’esempio qui sotto è utilizzata per ordinare un array di valori di tipo string in ordine alfabetico inverso. Ecco la matrice iniziale da ordinare:

far nomi = [“Chris”, “Alex”, “Ewa”, “Barry”, “Daniella”]

La funzione di ordinamento accetta due argomenti:

Un array di valori di tipo noto (string).

Una chiusura che prende due argomenti dello stesso tipo,  comead esempio il contenuto di una matrice,  e restituisce un valore Bool per dire se il primo valore dovrebbe apparire prima o dopo il secondo valore, una volta che i valori stessi sono ordinati. La chiusura di ordinamento deve restituire true se il primo valore dovrebbe apparire prima del secondo valore, e false nel caso in cui il valore debba apparire dopo il secondo valore.

Questo esempio è un Ordinamento di un array di valori stringa, quindi la chiusura di smistamento deve essere una funzione di tipo (String, String) -> Bool.

Un modo per garantire la chiusura di ordinamento è quello di scrivere una normale funzione del tipo corretto e di passarla come secondo parametro della funzione di ordinamento:

func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}
var reversed = sort(names, backwards)
// reversed is equal to [“Ewa”, “Daniella”, “Chris”, “Barry”, “Alex”]

Se la prima stringa (s1) è maggiore della seconda stringa (s2), la funzione restituirà vero, indicando che s1 dovrebbe comparire davanti s2 nell’ array ordinato. Per i caratteri in stringhe, “superiore” significa “appare più avanti in alfabeto che”. Ciò significa che la lettera “B” è “superiore” la lettera “A”, e la stringa “Tom” è superiore della stringa “Tim”e così via.

Tuttavia, questo è un modo piuttosto complesso per scrivere ciò che è essenzialmente una funzione riassumibile nella singola espressione  (a> b).

Closure Expression Syntax

Le sintassi delle espressioni di chiusura in generale si presentano in questa forma:

{(Parametri) -> tipo di ritorno in
dichiarazioni
}

Le sintassi delle espressioni di chiusura possono utilizzare parametri costanti, parametri variabili e parametri inout. Si possono utilizzare Tuple come tipi di parametri.

L’esempio seguente mostra un’espressione di chiusura della funzione di ordinamento inverso:

invertito = sort (nomi, {(s1: String, s2: String) -> Bool in
return s1> s2
})

Si noti che la dichiarazione di parametri e del tipo di ritorno per questa closure è identica alla dichiarazione dalla funzione all’inverso. In entrambi i casi, è scritto come (s1: String, s2: String) -> Bool. Tuttavia, per l’espressione di chiusura in linea, i parametri e il tipo restituito sono scritte all’interno delle parentesi graffe, non al di fuori di esse.

L’inizio del corpo della chiusura è introdotto dalla parola chiave “in”. Questa parola indica che la definizione di parametri e dei tipi di ritorno della chiusura è terminata e il corpo vero e proprio della chiusura sta per iniziare.

Poiché il corpo della chiusura è relativamente breve, può anche essere scritto su una sola riga:

reverse = sort (nomi, {(s1: String, s2: String) -> Bool in cambio s1> s2})
Questo dimostra che la chiamata generale per la funzione di ordinamento è rimasta la stessa. L’intera serie di argomenti è ancora contenuta in due parentesi. Tuttavia, uno di questi è ora una chiusura inline.

Inferring Type From Context

Poiché la chiusura di ordinamento viene passato come argomento a una funzione, Swift può dedurre i tipi dei suoi parametri e il tipo del valore restituito . Questo parametro è in attesa di una funzione di tipo (String, String) -> Bool. Ciò significa che la stringa, di tipo String, e Bool non deve necessariamente essere scritta come parte della definizione dell’espressione chiusura. Poiché tutti i tipi di dato possono essere dedotti, la freccia di ritorno (->) e le parentesi intorno ai nomi dei parametri possono anche essere omesse:

invertito = sort (nomi, {s1, s2 in cambio s1> s2})

È sempre possibile dedurre i tipi dei parametri e il tipo di ritorno quando si passa una chiusura a una funzione come espressione di chiusura di linea. E’ raramente necessario scrivere una chiusura in linea nella sua forma completa.

Tuttavia, se lo si desidera,  è possibile scriverla in forma completa; così facendo si rende il codice maggiormente leggibile nel caso in cui bisogna apportarvi qualche modifica in futuro. Nel caso della funzione di ordinamento, lo scopo della chiusura è evidente dal fatto che lo smistamento dei valori è avvenuto.


Implicit Returns from Single-Expression Closures

Chiusure ad espressione singola possono implicitamente restituire il risultato della loro singola espressione omettendo “return” dalla loro dichiarazione, come in questa versione dell’esempio precedente:

invertito = ordinamento (nomi, {s1, s2 in s1> s2})
In questa riga, il tipo di funzione del secondo argomento, specifica che il valore Bool deve essere restituito dalla chiusura. Poiché il corpo della chiusura contiene una singola espressione (s1> s2) che restituisce un valore Bool, non c’è ambiguità, e return può essere omesso.


Shorthand Argument Names

Swift fornisce automaticamente i nomi degli argomenti abbreviati all’inline di chiusura, che può essere utilizzato per fare riferimento ai valori degli argomenti della chiusura con i nomi $ 0, $ 1, $ 2, e così via.

Se si utilizzano questi nomi degli argomenti all’interno di un’espressione di chiusura, è possibile omettere la definizione del tipo della lista, e il numero e il tipo dei nomi degli argomenti in essa contenuti, i quali saranno dedotti dal tipo di funzione prevista. Ad esempio si può procedere nel seguente modo:

reverse = sort (nomi, {$ 0> $ 1})
Qui, $ 0 e 1 $ si riferiscono al primo e secondo argomento String della chiusura.


Operator Functions

In realtà c’è un modo ancora più breve di scrivere l’espressione di chiusura di cui sopra. Il tipo String di Swift definisce la sua applicazione specifica (per quanto riguarda una stringa) dell’operatore di maggiore (>) come una funzione che ha due parametri di tipo String, e restituisce un valore di tipo Bool. Ciò corrisponde esattamente al tipo di funzione necessaria per il secondo parametro della funzione di ordinamento. Pertanto, si può semplicemente passare l’operatore di maggiore, e Swift deduce che si desidera utilizzarlo per ordinare dei valori di tipo string:

invertito = sort (nomi,>)

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