In questo articolo passeremo in rassegna gli strumenti che Swift mette a disposizione dello sviluppatore per controllare il flusso di esecuzione del codice. Dato che si suppone che il lettore abbia già precedente esperienza con linguaggi di programmazione derivanti dal C, ci soffermeremo a sottolineare le differenze sulla sintassi e sulla semantica rispetto al funzionamento classico.
Cicli: for e for-in
Nelle prime versioni, Swift supportava due varianti del ciclo for
. A partire dalla versione 3.x, la sintassi di questo ciclo, proveniente dal C, è stata deprecata. Adesso, l'unica sintassi supportata è quella del più moderno for-in, che ci permette di iterare su un range, un array, una collection o una stringa.
Partiamo dal classico esempio per la stampa dei numeri interi da 1 a 10. Usando il ciclo for-in
e l'operatore di range, otterremo quanto segue:
for i in 1...10 {
print(i)
}
Notiamo che in Swift le parentesi non sono obbligatorie (sebbene possano essere utilizzate, se lo si preferisce, per questioni di leggibilità).
In Swift troviamo due operatori di range: range aperto, espresso usando la notazione ..<
e range chiuso, con la notazione ...
. Agli estremi si indicano i valori di inizio e di fine del range. La differenza tra range aperto o chiuso, sta nel fatto di includere (chiuso) o meno (aperto) il valore finale. Nell'esempio precedente, nell'ultima iterazione del ciclo, i
assume il valore 10
. Se avessimo voluto scrivere lo stesso ciclo con l'operatore di range aperto, avremmo usato la seguente notazione: 1..<11
.
Il costrutto for-in
ci permette inoltre di iterare su un array in maniera molto intuitiva. Se supponiamo di avere un elenco di frutti:
let frutta = ["mela", "pera", "pompelmo", "ananas", "fragola"];
e vogliamo stampare sulla console ogni singolo frutto, possiamo usare questo costrutto:
for f in frutta {
print(f)
}
In maniera del tutto simile, possiamo accedere ad ogni singolo carattere che compone una stringa:
let longword = "supercallifragilisticaespiralitoso"
for c in longword {
print(c)
}
Infine, se vogliamo iterare su tutte le coppie chiave-valore di una collezione, come la seguente:
let auto = ["marca": "Audi",
"modello": "Q3",
"colore": "alpine white",
"concessionario": "Audi Zentrum"]
possiamo nuovamente utilizzare il ciclo for-in
:
for (chiave, valore) in auto {
println("\(chiave) : \(valore)")
}
In questo esempio, tuttavia, utilizziamo una tupla, un tipo che tratteremo nelle prossime lezioni.
Notiamo che in tutti gli esempi di uso del for-in
, abbiamo usato un identificatore che ci permette di accedere al valore corrente dell'iterazione. Questa è in realtà una costante implicita, che non è necessario dichiarare con let
. Lo scope (o ambito di validità) della costante è il corpo del ciclo, e dunque non potrà essere utilizzata al di fuori.
Cicli: while e repeat-while
I cicli while
e do-while
hanno una sintassi e semantica pressoché identica ai tradizionali costrutti del C while e do-while. L'unica differenza è l'utilizzo opzionale delle parentesi per indicare la condizione d'uscita:
var i = 1
while i <= 10 {
print(i)
i+=1
}
Utilizziamo adesso il costrutto repeat-while
per stampare i numeri da 10 a 1:
repeat {
println(i)
i-=1
} while i > 0
break e continue
Anche in Swift, come in C, esistono le parole riservate break
e continue
che ci permettono rispettivamente di concludere prematuramente un ciclo o di saltare l'iterazione corrente, continuando con le successive.
Vediamo due esempi:
for i in 0..<10 {
if i == 5 {
break
} else {
print("\(i)")
}
}
Il precedente blocco di codice stamperà solo i numeri da 0 a 4, perchè l'istruzione break
terminerà il ciclo non appena i
assumerà un valore pari a 5.
Nel prossimo esempio invece sfruttiamo la parola riservata continue
per stampare i numeri dispari da 0 a 10 in ordine decrescente:
for i in (0..<10).reversed() {
if i % 2 == 0 {
continue
}
print("\(i)")
}
Nel precedente ciclo, se i
ha valore pari, il resto del ciclo viene ignorato e il compilatore valuterà direttamente la prossima iterazione del ciclo.
Istruzioni condizionali
Abbiamo già visto negli articoli precedenti che Swift fornisce il classico costrutto condizionale if-else
:
if num > 0 {
print("numero positivo")
} else if num == 0 {
print("zero")
} else {
print("numero negativo")
}
Di nuovo, come nei costrutti precedenti, le parentesi sono opzionali per la condizione. Ma la grossa differenza rispetto al C è che la condizione deve essere necessariamente di tipo booleano! In Swift, una variabile con valore 0 o con valore nil
non è automaticamente considerata false
come in C. Il seguente codice:
if num {
print("positivo")
}
genererà infatti l'errore seguente:
'Int' is not convertible to 'Bool'
La sintassi corretta per precedente blocco è:
if num > 0 {
print("positivo")
}
Ricordiamo infine che è possibile utilizzare l'istruzione break
per uscire prematuramente dal corpo di un if
nel caso fosse necessario.
Nel prossimo articolo infine vedremo il costrutto switch
che in Swift è tutto nuovo e molto più potente rispetto a quello originale del C e merita trattazione a parte.
A questo link è disponibile il Playground completo con tutti gli esempi usati in questa lezione.