2. Cicli e funzioni Flashcards

1
Q

La sintassi del ciclo for del linguaggio Swift

A

Come funziona un ciclo con il linguaggio Swift?

Nei linguaggi di programmazione in generale, quindi non solo per Swift, un ciclo rappresenta la capacità di ripetere un blocco di istruzioni. In più, un ciclo, può variare lo stato delle variabili del blocco in base a dei particolari criteri che vedremo man mano.

In pseudo codice, potrei razionalizzare un ciclo, in questa maniera:

ripeti per 10 volte {

print(“ciao xCoders”)

}

Cioè, esisterà una parola chiave o keyword che farà in modo di ripetere per n volte (nell’esempio 10) un blocco di codice (nell’esempio, stamperà per 10 volte la scritta “ciao xCoders”).

Se hai capito questo semplice esempio in pseudo codice, trasformarlo con il linguaggio Swift sarà, spero, altrettanto semplice.

La prima tipologia di ciclo, perché nè esistono diversi, si chiama ciclo for-in.

La sintassi è definita:

  1. Dalla parola chiave for.
  2. Seguita dal nome di una variabile chiamata, in gergo, iteratore.
  3. Dalla parola chiave in.
  4. E da un’intervallo di valori.

Più facile a farsi che a dirsi. Questa è la sintassi classica di un ciclo for in Swift:

for <iteratore> in <intervallo> {</intervallo></iteratore>

<blocco></blocco>

}

Puoi leggerla così: per ogni valore, contenuto nell’intervallo, esegui il blocco d’istruzioni.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Rappresentare un range o intervallo di valori

A

Facciamo una piccola digressione sui range di numeri in Swift.

Un range è la rappresentazione contratta di un array di Int. Viene definito il primo elemento x e l’ultimo elemento y, tra x e y vengono messi tre puntini (…) che stanno ad indicare che da x a y ci stanno tutti gli interi compresi tra x e y (x<=…<=y) come se fosse un array indicato solo con il valore della testa e della coda.

Quindi il range di numeri che comprende 1 e 10 si scrive così:

var range = 1…10

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Il primo esempio ed il simbolo Underscore

A

Partiamo dall’esempio più semplice: stampare 10 print con 10 numeri diversi:

print(“1”)

print(“2”)

print(“3”)

print(“4”)

// ecc fino a 10

Quello che vuoi fare è creare un ciclo che, per ogni valore da 1 a 10, esegua l’istruzione print. Ogni volta, però, cambiando il numero da stampare.

Quindi, se volessi stampare i numeri da uno a dieci ti dovrai avvalere sicuramente del range 1…10.

Proviamo a scrivere un primo ciclo.

Gli elementi che abbiamo, per completare tutta la sintassi del ciclo, sono: la parola chiave for, la in ed il range. Ci manca la variabile o iteratore.

for <iteratore> in 1...10 {</iteratore>

// da definire

}

Per il momento, al posto del campo iteratore, puoi inserire il simbolo underscore _ che ti fa omettere questo passaggio:

let range = 1…10

for _ in range {

print(“ciao xCoders”)

}

Come si usa il campo iteratore?

Il campo variabile, o anche detto iteratore, assume, ad ogni ciclo, un valore del range da passare a rassegna. Puoi pensarlo come ad una variabile che ha lo scopo di assumere, ad ogni giro del ciclo, il valore del range successivo al precedente.

L’iteratore, la prima volta che viene eseguito il ciclo, assume il primo valore del range. Nel nostro caso, assumerebbe il valore 1 (dato che il range 1…10 parte dal valore 1).

Fin quando non vengono eseguite tutte le istruzioni del ciclo, quella variabile iteratore continuerà a mantenere il valore 1 e quindi, quel valore, potrà essere letto all’interno del blocco del ciclo per eseguire delle operazioni (per esempio la stampa). A fine ciclo, l’iteratore passa al valore successivo del range e continuerà così fin quando non termineranno tutti gli elementi del range.

Adesso, 2 cose dovrebbero essere chiare:

Indifferentemente dalla presenza o meno di una variabile, il ciclo, esegue tante volte il blocco d’istruzioni quanti sono gli elementi del range. Se il Range è di 100 elementi, il ciclo verrà eseguito per 100 volte.

La variabile di lettura o iteratore viene inserita solo quando si vuole utilizzare il valore del range, letto dal ciclo, all’interno del blocco d’istruzioni.

Esercizio 1. Stampare i numeri da 4 a 10.

Stampa i numeri che vanno da 4 a 10.

for iteratore in 4…10 {

print(iteratore)

}

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Variabili interne ed esterne al ciclo

A

Ogni blocco d’istruzioni del ciclo devi immaginarlo come ad un qualcosa che viene eseguito ed infine resettato alla fine delle istruzioni presenti.

Per capire quello che voglio dire, prova a risolvere questo esercizio.

Esercizio 2. Crea una variabile con valore 10 che viene incrementata di una unità per quanti sono i valori presenti in un range. Per esempio, se il range è 1…4. La variabile, a fine ciclo, dovrà avere il valore 14 (perché nel range ci sono 4 numeri, quindi ad ogni numero del range ha sommato +1 al numero).

La tentazione del giovane sviluppatore è quella di scrivere qualcosa del genere:

for _ in 1…4 {

var numero = 10

numero += 1

print(numero)

}

Riesci a dirmi cos’è che fa questo ciclo? Se non ti arriva l’illuminazione divina, invece di sparare una risposta a caso, prendi il codice ed incollalo nel Playground.

Alla prima esecuzione, il ciclo si trova a leggere l’elemento 1 del range, entra dentro il blocco ed inizializza la variabile numero con il valore 10. Poi gli incrementa il valore di 1 (il simbolo += l’ho spiegato a metà di questa lezione) e stampa il contenuto della var.

Una volta finite tutte le istruzioni del blocco, al solito, controlla se ci sono o no altri elementi nel range da scorrere. Dato che si trova ancora alla posizione 1, ci sono altre 3 unità da scorrere. Il ciclo passa al valore numero 2.

Letto il numero 2 del range, rientra dentro il blocco e qui accade quello che non volevamo accadesse.

Ad ogni ciclo, la variabile numero viene inizializzata nuovamente al valore di 10. Quindi, la variabile numero dimentica tutto quello che è stato fatto nel ciclo precedente.

Come si risolve?

Si può adottare un piccolo stratagemma. Se inizializzi la variabile numero fuori dal ciclo, il suo valore non verrà mai sovrascritto a meno che non ordinato da te:

var numero = 10

for _ in 1…4 {

numero += 1

print(numero)

}

Dato che la var numero è stata inizializzata prima, ogni blocco la incrementerà sempre di un valore fin quando non avrà finito di passare a rassegna tutti i valori del range.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Array e ciclo for-in

A

Con il ciclo for in Swift sei in grado di leggere anche gli elementi di un array e di un dizionario in maniera intuitiva e veloce.

Riprendiamo velocemente cos’è un array. Sai, dalla lezione degli array e dizionari in Swift, che ogni elemento è conservato in una sorta di vagone identificato da un indice.

var treno = [

“linguaggio swift”,

“c”,

“objective-c”,

“Apple”

]

treno[0]

treno[1]

treno[2]

treno[3]

Con il ciclo for ed il linguaggio Swift sei in grado di passare a rassegna tutti i valori dell’array spostandoti da una posizione all’altra del treno proprio come hai visto fare con i range di numeri.

Nel caso degli array, se volessi scorrere i suoi elementi con il ciclo for, ti basterebbe inserire il suo nome dopo la parola chiave in:

for <iteratore> in <array> {</array></iteratore>

}

Se, nel range, la variabile iterativa leggeva uno ad uno i valori del range, nel vettore, l’iteratore legge i valori dell’array partendo dalla posizione 0.

Quindi, se all’interno del blocco d’istruzioni stampi il valore dell’iteratore, sulla console spunterà il valore di ogni elemento dell’array:

var treno = [

“linguaggio swift”,

“c”,

“objective-c”,

“Apple”

]

for vagone in treno {

print(vagone)

}

La storia è sempre la stessa:

Al primo giro la variabile vagone legge il contenuto dell’array alla posizione 0.

Entra dentro il blocco d’istruzioni e stampa “linguaggio swift“.

Finito il codice dentro il blocco, controlla se ci sono altri elementi da leggere.

Se ci sono torna alla riga for e la variabile vagone prende il contenuto dell’array in posizione 1. Entra nel blocco e stampa “c”.

Continua così fin quando non ha finito.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Dizionario e ciclo for

A

Considerata la presenza delle chiavi e dei valori, il ciclo for in Swift, si complica un pochino:

for <(chiave, valore)> in <dizionario> {</dizionario>

}

Ogni elemento di un dizionario del linguaggio Swift è composto sempre da due parti: una chiave ed un valore. Per questo motivo il ciclo deve poter leggere entrambe le parti in un unico colpo. Un po’ come se entrassi in un vagone composto da due cabine.

La variabile iteratrice viene definita da una coppia di variabili, racchiuse in parentesi tonde e divise da una virgola: (chiave, valore).

La variabile a sinistra della virgola leggerà sempre la chiave.

La variabile a destra della virgola leggerà sempre il valore associato alla chiave.

Applichiamolo ad un esempio.

Esercizio 3. Crea un dizionario la cui chiave rappresenta il nome di un dipendente di un’azienda ed il valore il suo salario. Crea un ciclo che stampa il nome ed il salario del dipendente.

let stipendiDipendenti = [“Giuseppe”: 1200.00, “Matteo”: 560.30, “Delia”: 2000.55, “Luca”: 755.99]

for (dipendente, stipendio) in stipendiDipendenti {

print(“Il dipendente (dipendente) guadagna (stipendio) “)

}

In alternativa puoi utilizzare una sola variabile iteratrice. La variabile ti permette di accedere sia alla chiave che al valore e per farlo devi inserire .0 per la chiave e .1 per il valore.

let stipendiDipendenti = [“Giuseppe”: 1200.00, “Matteo”: 560.30, “Delia”: 2000.55, “Luca”: 755.99]

for dipendente in stipendiDipendenti {

print(“chiave: (dipendente.0) valore: (dipendente.1) “)

}

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

While e Switch in Swift. Un altro modo per esprimere ciclicità e controllo

A

Con la lezione precedente, interamente incentrata sul ciclo for del linguaggio Swift, hai appreso che esiste un modo velocissimo per eseguire tante istruzioni con una manciata di righe di codice.

Come la programmazione ci insegna non esiste né un solo modo né una sola sintassi per risolvere un problema.

Ecco perché, in questa lezione, voglio estendere le tue conoscenze in materia di cicli e istruzioni di controllo, ti parlerò del ciclo while e ti introdurrò una nuova istruzione condizionale, lo switch.

Aspetta un secondo Peppe.

Perché dovrebbero esistere diversi modi per scrivere un ciclo o per fare un controllo del codice?

Il motivo per cui il linguaggio Swift, come anche altri linguaggi, utilizzano diverse parole chiave per esprimere lo stesso concetto, è paragonabile allo scegliere, o meno, una strada A piuttosto ché una strada B per raggiungere un punto.

Mi spiego meglio.

Durante lo sviluppo delle tue future applicazioni, ci saranno casi in cui, utilizzare un sistema o l’altro renderà più snello e leggibile il codice da te scritto.

Ovviamente esistono motivazioni di carattere tecnico che non terrò in considerazione in questo corso. Considerazioni che sono alla base della scelta del percorso A o B. La strada A, per esempio, è più veloce ma più usurante per la vettura (come una strada che taglia per una montagna), mentre la strada B è più lenta ma meno pesante per il guidatore.

Detto ciò, sei pronto a studiare l’istruzione While e Switch in Swift?

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

While e Repeat-While. Altri modi per esprimere la ciclicità con il linguaggio Swift

A

Oltre al ciclo for, il linguaggio Swift, mette a disposizione anche il ciclo while e repeat-while.

Il meccanismo è sempre lo stesso, eseguono in modo ricorsivo un numero determinato di istruzioni fin quando una certa condizione non è più verificata.

Il ciclo while in Swift lo chiamerai a condizione iniziale quando prima verifica che la condizione è vera e poi esegue il ciclo:

while <condizione> {</condizione>

<istruzioni></istruzioni>

}

var i = 0

while i < 5 { // finché i è < 5 esegui il ciclo

print(i += 1)

} // ad ogni ciclo ricontrollerà sempre la condizione

Mentre il ciclo repeat-while lo chiamerai a condizione finale quando la condizione di verifica si troverà alla fine. Quindi, prima esegue sempre un’istruzione e poi ne verifica la condizione:

repeat {

<istruzionii></istruzionii>

} while <condizione></condizione>

var i = 0

repeat {

i++

print(i)

} while i < 10

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

L’istruzione Switch. Gestire il flusso d’esecuzione in maniera intuitiva

A

Lo switch puoi considerarlo come un parente dell’istruzione if-else.

La sua caratteristica è quella di controllare lo stato di un valore e creare dei particolari blocchi di codice che si attivano solo se quel valore corrisponde al particolare caso da “acchiappare”.

Peppe, e che vor di?

Ti faccio vedere la sintassi e poi te la spiego:

switch variabileControllata {

case valore_1:

risponde al valore_1

case valore_2, valore_3:

risponde sia al valore_2 che al 3

default:

in caso contrario fai qualcos’altro

}

Un blocco di codice si attiva solo quando la variabileControllata è uguale ad uno dei valori dei case.

Mi spiego meglio, al solito, facendoti un esempio.

Esercizio 0. Implementa una istruzione switch che controlli se la lettera contenuta in una variabile è una vocale, consonante oppure nessuna dei due.

let unCarattere = “a” //cambia questo carattere per vedere altre possibilità

switch unCarattere {

case “a”, “e”, “i”, “o”, “u”:

print(“(unCarattere) è una vocale”)

case “b”, “c”, “d”, “f”, “g”, “h”, “l”, “m”, “n”, “p”, “q”, “r”, “s”, “t”, “v”, “z”:

print(“(unCarattere) è una consonante”)

default:

print(“(unCarattere) non è un né una vocale né una consonante”)

}

Ogni blocco d’istruzioni di un case comincia dopo i due punti.

Lo switch controlla il valore della variabile, entra dentro il codice, esegue il case dove il valore della variabile è acchiappato ed infine esce dallo switch.

A differenza dell’if-else, qui, il blocco di codice non ha bisogno di essere racchiuso da delle parentesi graffe. Basta inserirlo dopo i due punti che definiscono il case da considerare.

  1. Ogni case ha bisogno di almeno un’istruzione.
  2. L’intera istruzione switch deve sempre contenere un case di tipo default.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Stesso esempio con l’istruzione if-else

A

Ah si! Ti dicevo che è un parente dell’if else perché una logica di questo genere l’avresti potuta scrivere così:

var lettera = “a”

if (lettera == “a” || lettera == “e”) {

print(“(lettera) è una vocale”)

} else if (lettera == “b”) {

print()

} else {

print(“non è né una vocale né una consonante”)

}

Come puoi notare, utilizzando l’if-else avresti perso decisamente molto più tempo a scrivere il codice di controllo.

Quindi, già da questo semplice esempio, puoi cominciare a capire come le diverse istruzioni ti permetteranno di ottenere un codice migliore in base al tipo di problema.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Case che acchiappano intervalli di valori

A

Ci sono casi in cui ti piacerebbe controllare se un numero appartiene o meno ad un determinato intervallo.

Per esempio, proviamo a scrivere la logica per il controllo della vita di un giocatore.

Se la vita del giocatore, che come massimo è di 100 hp, si dovesse trovare nell’intervallo tra 50 e 0 allora diremo che è in fin di vita. Se invece si trovasse sopra i 50 e fino a 100, il giocatore sarà in buona salute. Altrimenti, se la vita dovesse essere 0, sarà morto.

Con lo switch del linguaggio Swift, per controllare se un valore è compreso tra due numeri, devi utilizzare il Range. I range li hai incontrati nella lezione del ciclo for-in. Per esempio i numeri che vanno da 0 a 50, si esprimono come range 0…50.

Con uno switch, questo esercizio può essere scritto così:

var hp_giocatore = 50 // cambia per vedere il risultato

switch hp_giocatore {

case 51…100:

print(“il giocatore è in ottima forma”)

case 1…50:

print(“il giocatore è in fin di vita”)

case 0:

print(“il giocatore è morto!!”)

default:

print(“valore non consentito max 100 e min 0 “)

}

Una cosa che salta subito all’occhio è la pulizia del codice rispetto all’equivalente con if-else.

Perché, tu hai già scritto lo stesso esercizio con l’if-else vero? Fallo immediatamente per rendertene conto tu stesso!

Tip. Nel caso in cui volessi escludere gli estremi, puoi utilizzare la forma del range contratto. Ovvero puoi scrivere un range in questo modo:

1..<50

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Break, continue, fallthrough e return. I controllori del codice in swift

A

Il codice, come hai visto e appreso, viene eseguito a cascata ovvero parte dalla linea 1 e finisce alla linea x.

Esistono delle parole chiave che alterano il normale svolgimento a cascata,permettendo di saltare da un blocco di codice ad un altro.

Si chiamano break, continue, fallthrough e return. Le prime 3 te le spiegherò in questa lezione mentre l’ultima nella lezione sulle funzioni.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Continue

A

La parola continue comunica di andare avanti spostando l’esecuzione al prossimo ciclo. Un po’ come se dicesse: “Hei, io ho fatto quello che dovevo fare, puoi saltare avanti al prossimo ciclo senza dover finire l’attuale“.

Esercizio 3. Crea il codice che rimuove tutte le vocali da una stringa formando così una stringa semi criptata.

let stringaNonCriptata = “laMiaPassword”

var stringaCriptata = “”

for carattere in stringaNonCriptata.characters {

switch carattere {

case “a”, “e”, “i”, “o”, “u” :

continue // se trova una vocale va avanti al prossimo carattere (quindi al prossimo ciclo)

default: // se non è una vocale inserisce il carattere

//nella nuova stringa criptata

stringaCriptata.append(carattere)

}

}

print(stringaCriptata)

Senza la parola chiave continue non saresti riuscito a risolvere il problema dato che ogni case ha bisogno per forza di un’istruzione da eseguire.

Hai avuto problemi a capire il funzionamento di questa istruzione? Fammelo sapere con un commento! noi non mangiamo sviluppatori.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Break, fermati!

A

Se continue permetteva di “continuare”, scusa il gioco di parole, break arresta immediatamente l’esecuzione di un blocco di codice.

Break in un ciclo: Il break in un ciclo interrompe immediatamente l’esecuzione di tutto l’intero ciclo senza permettergli di andare ai successi.
L’esecuzione passa, dal ciclo, alla riga di codice immediatamente sotto la parentesi graffa } che chiude il ciclo.
Nell’esempio utilizzeremo il break per interrompere il salvataggio di una stringa appena incontra uno spazio vuoto.

let stringaSenzaSpaziVuoti = “AAAA BBBB” // questa stringa contiene uno spazio vuoto trs AAAA e BBBBB

var stringaFinale: String = “ “

for carattere in stringaSenzaSpaziVuoti.characters {

if (carattere == “ “) {

break

}

stringaFinale.append(carattere)

}

print(stringaFinale)

Il ciclo qui sopra avrebbe dovuto stampare tutta la stringa “AAAA BBBB” ma, avendo messo come condizione l’uscita dal ciclo quando trovato uno spazio vuoto, non ha la possibilità di farlo.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Continue o Break? Impara ad ottimizzare i tempi d’esecuzione

A

Saper mettere correttamente i break al posto giusto è quello che fa la differenza tra un buon programmatore e un programmatore.

Ogni riga impiega del tempo per essere eseguita.

Immagina che una stringa sia lunga migliaia e migliaia di elementi (ancora peggio se è un array o dizionario), il tuo compito è quello di scovare l’elemento intruso e di interrompere l’esecuzione al ritrovamento dello stesso.

Esercizio 4. Ferma l’esecuzione del ciclo al ritrovamento del carattere “1”, cerca di ottimizzare i tempi!

var stringa = “aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1aaaaaaaaaaaaaaaaaaaaaaaaa”

var i = 0

for valore in stringa.characters {

if (valore == “1”) {

print(“trovato intruso”)

continue // puoi anche non mettere niente

}

i += 1

print(“ciclo eseguito (i) volte”)

}

Con il continue il ciclo viene eseguito 82 volte, ovvero la stringa viene letta per intero anche se ha trovato l’elemento intruso. Con il Break il ciclo viene eseguito 57 volte. Questa è quello che intendo per ottimizzazione del codice.

var stringa = “aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1aaaaaaaaaaaaaaaaaaaaaaaaa”

var i = 0

for valore in stringa.characters {

if (valore == “1”) {

print(“trovato intruso”)

break

}

i += 1

print(“ciclo eseguito (i) volte”)

}

Anche se per adesso non sembra che ci sia differenza tra i due tipi di implementazione, quando passerai allo sviluppo delle applicazioni ti renderai conto dei tempi biblici che ci vogliono per cercare e recuperare informazioni da database e quant’altro.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Fallthrough

A

E se volessi unire più case in uno switch?

Fallthrough fa al caso tuo permettendoti, una volta incontrata questa parola chiave, di eseguire il case immediatamente successivo.

Esercizio 5. Quando un numero intero è anche numero primo?

let interoDaDescrivere = 5 // provate a mettere 22 e vedrete che non si concatenano più il case con il default

var descrizione = “Il numero (interoDaDescrivere) è”

switch interoDaDescrivere {

case 2, 3, 5, 7, 11, 13, 17, 19:

descrizione += “ un numero primo, e anche”

fallthrough

default:

descrizione += “ un intero.”

}

print(descrizione)

//”Il numero 5 è un numero primo, e anche un intero.”

Se il numero interoDaDescrivere appartiene al case allora innescherà anche il fallthrough che eseguirà il case default.

17
Q

Le funzioni in Swift. Definizione e chiamata di una funzione

A

Le funzioni del linguaggio Swift, come di tutti i linguaggi, puoi pensarle come ad un apparato del nostro organismo.

Per esempio, le puoi paragonare all’apparato digerente che è composto dallo stomaco e altre parti. L’apparato prende in ingresso il cibo dalla bocca, lo trasforma all’interno della panza e lo espelle dall’orifizio più famoso al mondo.

Le funzioni puoi immaginarle simili allo stomaco. Prendono in ingresso un’informazione, la elaborano e la restituiscono all’applicazione.

Ti faccio un altro esempio banalissimo che sono sicuro capirai al volo. La macchina.

L’autovettura, per camminare, ha bisogno della benzina. Benzina che viene trasformata in energia permettendo alle ruote di farle muovere.

La macchina, intesa come sistema formato da più parti, sappiamo che: mettendo la benzina (che è il nostro ingresso) restituisce, come risultato di un’elaborazione, il movimento (trasformazione della benzina in energia e quindi uscita del sistema).

Nessuno qui, però, a parlato di come il cibo viene trasformato in energia e di come la benzina viene convertita in movimento. Non ne ho volutamente parlato perché le funzioni mascherano proprio questo passaggio.

Le funzioni servono a mascherare procedimenti a volte complessi.

Un po’ come i componenti di una macchina. Sai che ci sono, sai che servono a far funzionare l’autovettura ma non sai da cosa sono composti.

In poche parole, una funzione del linguaggio Swift, come per i componenti della macchina, servirà a scomporre il codice in tanti sotto codici che coopereranno per il funzionamento del programma.

La differenza?

Dato che devi diventare uno sviluppatore, dovrai creare il componente (la funzione) e dovrai definirne il suo comportamento (scriverne il codice).

Ma non demordere, se sei già arrivato a questo punto sei sulla buona strada dello sviluppatore di applicazioni iOS! Ma, prima di cantar vittoria, vediamo cosa sono queste famigerate funzioni del linguaggio Swift.

Sei pronto? Allora diamo il via alle funzioni in Swift!

18
Q

Il paradigma di programmazione Divide et Impera

A

Cominciamo da dare qualche definizione tecnica a ciò che farai.

Fin da scuola sei stato abituato a risolvere un problema step by step. Ovvero dato un problema, parti da una soluzione generale fino ad arrivare al caso particolare.

Quello che si fa nella norma è dividere un problema in tanti sotto problemi.

Come accendo una macchina?

Giro la chiave, e questa operazione cosa comporta?

L’accensione delle candele. Questa cosa farà?

ecc ecc.

Pistoni in movimento.

Macchina accesa.

Ogni sotto problema risolve un pezzo del problema. La quale risoluzione totale è data dalla loro somma.

In informatica, dividere un problema in tanti sotto problemi, prende il nome di paradigma Divide et Impera.

Paradigma è una parola che, nei linguaggi di programmazione, definisce uno schema da seguire. Mentre Divide et Impera è una celeberrima frase latina che sta a significare dividi e conquista/governa.

Quando sentirai parlare di paradigmi informatici vorrà dire che dovrai utilizzare un certo modello o schema di programmazione.

Il sopracitato paradigma Divide et Impera sancisce e ti suggerisce di programmare utilizzando piccoli blocchi di codice definiti da funzioni.

Ti ricordi quando ti ho detto che la macchina è suddivisa in tanti piccoli pezzi? Ecco! La suddivisione in tanti piccoli pezzi è avvenuta grazie all’applicazione del paradigma divide et impera applicato all’ingegneria meccanica.

In poche parole, come per le autovetture, non troverai mai una macchina formata da un solo pezzo (una macchina intera formata da tutti i pezzi saldati), in informatica non troverai mai un programma formato da un codice senza funzioni.

19
Q

Definire, creare e utilizzare una funzione con il linguaggio Swift

A

La creazione di una funzione in Swift e il suo utilizzo è un processo che si può riassumere in 3 passaggi:

Definizione.

Creazione.

Utilizzo.

La sintassi standard è la seguente:

func nomeFunzione(<parametri>) -&gt; <uscita> {</uscita></parametri>

<corpo></corpo>

}

20
Q

1# Definire una funzione

A

Partiamo subito con un esempio, immagina di voler scrivere la funzione, il quale compito è salutare una persona generica.

Il primo passaggio da fare è quello di definirne il prototipo o definizione della funzione. Ovvero, occorre delineare il motivo e lo scopo per cui si sta creando la funzione.

Il motivo per cui noi stiamo creando una funzione è che magari, la nostra futura applicazione, dovrà salutare tante volte i nuovi utenti registrati. Quindi ci serve un sistema che eviti di riscrivere N volte lo stesso codice e, al tempo stesso, ci permetta di riutilizzarla quando vogliamo.

Con il linguaggio Swift, una funzione, viene definita a partire dalla parola chiave func seguita dal nome e da delle parentesi tonde.

func nomeFunzione()

21
Q

2# Creare il corpo della funzione

A

Non abbiamo finito qua!

Creato il nome o prototipo della funzione è necessario definirne il comportamento. Dopo le parentesi tonde vanno inserite le parentesi graffe. All’interno delle graffe viene messo il codice della funzione.

Il cuore della funzione sta tutto qui dentro.

Nel caso della funzione salutoGenerico, andrai a mettere all’interno una print con un messaggio standard:

func salutoGenerico() {

print(“Ciao, Utente”)

}

Il corpo della funzione è come l’interno del motore di una macchina. Dato che sei il costruttore della tua applicazione devi sapere cosa andare a mettere dentro le tue funzioni.

22
Q

3# Chiamare una funzione

A

Adesso che è stato definito il comportamento della funzione salutoGenerico è arrivato il momento di utilizzarla.

L’utilizzo di una funzione prende il nome di chiamata di una funzione:

func salutoGenerico() {

print(“Ciao, Utente”)

}

salutoGenerico() // chiamata di una funzione

La chiamata di funzione rappresenta l’azione vera e propria, un po’ come quando giri la chiave per mettere in moto la macchina. Il codice si attiva solamente quando l’utente chiama una funzione.

Una delle caratteristiche più interessanti di una funzione è quella che puoi richiamarle quante volte vuoi. Quindi puoi benissimo fare così:

func salutoGenerico() {

print(“Ciao, Utente”)

}

salutoGenerico() // chiamata di una funzione

salutoGenerico() // un’altra chiamata

salutoGenerico() // ancora un’altra chiamata

23
Q

Definire i parametri in ingresso della funzione

A

La tua macchina a Diesel, che tipo di carburante si aspetta di ricevere in ingresso?

La domanda è retorica. La macchina a Diesel se provata a caricare con la Benzina si guasterà sicuramente.

Anche le funzioni lavorano allo stesso modo delle macchine. Ai suoi parametri in ingresso vanno definiti, a priori, i tipi di dato che li rappresenteranno.

All’interno delle parentesi vanno inseriti i parametri in ingresso. La formula è abbastanza semplice: “nomeParametro: TipoDiDato“. Nell’esempio della tua funzione salutaPersona potremmo aggiungere un parametro di tipo String da utilizzare, all’interno del corpo, per stampare il suo valore:

func salutaPersona(parametro: String) {

print(“Ciao, (parametro)”)

}

Per rendere più comprensibile il funzionamento della funzione puoi cambiare il nome del parametro con uno più user friendly:

func salutaPersona(nome: String) {

print(“Ciao, (nome)”)

}

Esercizio 0. Crea una funzione che stampa un numero Intero passato come parametro.

func stampaIntero(numero: Int) {

print(numero)

}

Chiamare una funzione con parametro è semplicissimo con il linguaggio Swift. All’interno delle parentesi dovrai inserire il nome del parametro seguito dai due punti ed il valore/variabile da prendere in ingresso:

func salutaPersona(nome: String) {

print(“Ciao, (nome)”)

}

salutaPersona(nome: “Giuseppe”)

var delia = “Delia”

salutaPersona(nome: delia)

Se qualcosa non dovesse esserti chiara, per favore fammelo sapere con un commento. Qui sei in una fauna protetta dove tuteliamo i programmatori.

24
Q

Funzioni con più parametri in ingresso

A

Immaginiamo che la tua applicazione abbia due campi di testo. Uno per il nome ed uno per il cognome. All’interno dell’app hai creato una funzione che ti permette di mettere insieme queste due stringhe.

Ipotizziamo d’aver chiamato la funzione unisciDueStringhe. Come parametri in ingresso, dato che abbiamo detto che vogliamo unire nome e cognome, dovrai predisporre la tua funzione per accettare due parametri di tipo String.

Ogni parametro della funzione, si divide dall’altro, con una semplice virgola.

func unisciDueStringhe(nome: String, cognome: String) {

let stringaUnita = nome + “ “ + cognome

print(stringaUnita)

}

Anche in questo caso, la chiamata consiste nel riempire i due parametri con un valore o una variabile/costante.

25
Q

Tipo di dato d’uscita o return di una funzione

A

Esistono 2 tipi di funzioni: Ecologiche ed Inquinanti.

Non è un’esercitazione!

Come una macchina produce gas di scarico che riversa nell’ambiente, anche una funzione può produrre qualcosa da riversare nell’applicazione.

Una macchina ha come tipo in ingresso il combustibile e come tipo di uscita i gas di scarico. L’ipotetica funzione “consumaCarburante” prende la benzina e la trasforma, dentro il corpo della funzione, in gas di scarico.

Il gas di scarico, come il combustibile in ingresso, sono cose ben visibili a chi utilizza un’autovettura. Ci sei fin qua?

In poche parole, come il dato in ingresso, il dato in uscita è usufruibile dal resto del mondo/applicazione.

Per definire un tipo di uscita ad una funzione in Swift, dopo le parentesi tonde che definiscono il tipo in ingresso, si aggiunge una freccia -> seguita dal tipo di dato che manderà in output la nostra funzione.

Come al solito, eccoti un esempio pratico:

Esercizio 4. Modifica la funzione salutaPersona in modo da ottenere una funzione che ritorni la stringa contenente il saluto alla persona:

func salutaPersona(nome: String) -> String {

let saluto: String = “ciao (nome)” //creo una stringa con l’unione di ciao + nomePersona

return saluto //restituisco la stringa creata dentro la func

}

All’interno del corpo della funzione viene utilizzata una parola chiave, return, appartenente ai controllori del codice la quale permette di uscire da un blocco di codice restituendo un valore.

In questo caso la funzione prende in valore contenuto nel parametro, lo unisce ad una stringa e ritorna la stringa al mondo esterno.

Infatti quando provi a chiamare la funzione, questo è quello che accade:

// Puoi passare il valore di ritorno ad una variabile

var b = salutaPersona(nome: “Giuseppe”)

print(b) // Ciao Giuseppe

var c = “Matteo”

//oppure posso passarla alla print dato che salutaPersona() equivale ad un valore String

print(salutaPersona(nome: c)) // Ciao Matteo

Il mondo esterno utilizzerà solo il tipo di ritorno fregandosene di tutto quello che accade all’interno della funzione.

Esercizio 2. Crea la funzione che ritorna il doppio di un valore Double passato come parametro.

func calcolaDoppio(valore: Double) -> Double {

let doppio = valore * 2

return doppio // avrei potuto fare anche return valore*2

}

var a: Double = 4

print(“Il doppio di (a) è (calcolaDoppio(valore: a))”)

// il doppio di 4 è 8

Ti ricordo che la seguente sintassi: “(a)” e “(calcolaDoppio(valore: a))” converte in maniera esplicita e temporanea il valore in String. L’ho spiegato nella lezione sulle variabili e costanti del linguaggio Swift.

26
Q

Funzioni senza valore di ritorno

A

Le funzioni senza ritorno sono tutte quelle funzioni tronche, ovvero senza il simbolo ->.

Queste tipo di funzioni non è vero che non ritornano un valore, bensì lo fanno ma non si vede. Il valore di return si chiama Void o vuoto (diverso dal nil incontrato per l’opzionalità).

Oltre a non avere il tipo di ritorno possono comunque utilizzare la parola chiave return in modo da permettere l’uscita preventiva dalla funzione. Il return, per una funzione senza parametro di ritorno, non ha bisogno dell’esplicita assegnazione di un valore.

Esercizio 5. Crea la funzione che, inserito un valore, controlla se è maggiore di zero, se non lo è esce preventivamente:

func controllaNumero(ingresso: Int) {

if(ingresso < 0) {

print(“il numero è minore di 0”)

return

}

print(“il numero è maggiore di 0”)

}

In questo modo il return, una volta che l’esecuzione del codice è entrata dentro l’if, permette l’uscita preventiva dalla funzione dopo aver stampato il messaggio.

Il return senza parametro restituisce un void ed è presente implicitamente (anche se non si vede) a fine di ogni funzione senza parametro.

27
Q

Parametri d’uscita multipli

A

Se non è perché lo stai cercando, puoi saltare questo box dato che si tratta di una tecnica che non viene molto utilizzata.

Una funzione in Swift oltre ad accettare più parametri può restituire più valori. Questo serve per evitare di dover creare due funzioni con lo stesso codice ma con dati di ritorno differenti.

Il tipo di ritorno in questo caso sarà una Tupla.

Esercizio 6. Crea una funzione che, dato un array di interi in ingresso, restituisca una tupla contenente il valore max e il valore min dell’array:

func calcoloMinMax(array: [Int]) -> (min: Int, max: Int) {

var minimo = array[0] //setto minimo e massimo uguali al primo valore dell’array

var massimo = array[0]

for valore in array {

if valore < minimo {

minimo = valore

} else if valore > massimo {

massimo = valore

}

}

return (minimo, massimo)

}

var array = [123, 0, 22, -1, 155, 43]

let minMax = calcoloMinMax(array: array) // restituisce la tupla (min,max) che conservo in una costante qualsiasi

// ti ricordo che il tipo di dato viene acquistato all’inizializzazione. minMax ora rappresenta una tupla di tipo (min,max)

print(“il minimo è (minMax.min) e il massimo è (minMax.max)”) //accedo ai valori della tupla

//con .min e .max​

28
Q

Parametri di ingresso e uscita opzionali

A

E se il parametro d’ingresso fosse opzionale?

Per le funzioni puoi utilizzare l’opzionalità applicata ai parametri in ingresso o uscita (l’opzionalità l’ho introdotta nella lezione: opzionalità in swift).

Può capitare, sopratutto durante lo sviluppo delle applicazioni iOS, che ci siano delle funzioni (magari di sistema) che restituiscano nil al verificarsi di un problema.

Per prevedere e quindi trattare correttamente quest’eventualità puoi definire i parametri d’ingresso o uscita come opzionali.

Esercizio 7. Crea una funzione che conta il numero di elementi di un array. L’array passato può essere opzionale.

var mioArray: [Int]?

func contaElementi(array: [Int]?) {

if array == nil {

print(“il vettore è nullo per favore inizializzalo”)

return

}

print(“l’array contiene (array!.count) elementi”)

}

contaElementi(array: mioArray)

Nell’esempio la funzione può accettare il passaggio di un valore opzionale dato che il parametro è stato definito come opzionale. Nella chiamata della funzione, dato che il mioArray non era stato inizializzato, viene immediatamente attivato l’if che fa uscire preventivamente l’esecuzione dalla funzione.

In alternativa si può anche adoperare l’opzionalità al parametro d’uscita e quindi delegare la gestione del problema all’esterno della funzione:

var vettoreInteri: [Int]?

func contaElementi(array: [Int]?) -> Int? {

if array == nil {

return nil

}

return array!.count

}

if let numElementi = contaElementi(array: vettoreInteri) {

print(“l’array contiene (numElementi)”)

} else {

print(“per favore inizializza l’array”)

}

Non ti ricordi cos’è quella strana sintassi? Dai uno sguardo a questa lezione: opzionalità in swift.

29
Q

Parametro Inout

A

La modifica di un parametro di una funzione, fino ad ora, è impossibile. I parametri, di default, vengono considerati come costanti (let). Cioè, nel caso in cui ti servisse modificare, dall’interno della funzione, la variabile passata al parametro verrebbe a crearsi un problema:

var a = 2

func modifica(variabile: Int) {

variabile = 4 // Errore!!! Il parametro è considerato come let

}

Per poter risolvere questo problema, il linguaggio Swift ti mette a disposizione la parola chiave inout che permette di modificare direttamente la variabile passata come parametro.

Il parametro inout va inserito prima della definizione del tipo di dato del parametro:

func nomeFunc(parametro: inout Tipo) {} // Pseudo codice

Per capire meglio l’utilità del parametro inout, proviamo a creare una funzione che scambi i valori di due variabili:

var primo = 2

var secondo = 7

func scambiaValori(a: inout Int, b: inout Int) {

let c = a

a = b

b = c

}

Quando passi una variabile ad un parametro inout devi inserire il prefisso & seguito dal nome della var/let, il perché dell’inserimento di questo prefisso è un po’ complicato e molto grossolanamente serve ad avvisare la funzione che stai passando un riferimento ad una variabile presente nel progetto.

print(“(primo) e (secondo) “)

scambiaValori(a: &primo, b: &secondo)

print(“(primo) e (secondo) “)

Ora voglio farti riflettere su un problema di natura filosofica. Qual’è, secondo te, è l’approccio migliore? Questo:

var primo = 2

var secondo = 7

func scambiaValori() {

let c = primo

primo = secondo

secondo = c

}

scambiaValori()

o quello che hai visto prima utilizzando le funzioni inout? In effetti, anche la funzione senza inout ha risolto il problema.

Quindi Peppe, qual è la differenza?

La funzione senza inout sta venendo meno al problema della programmazione con funzioni.

Il compito delle funzioni è quello della semplificazione e del riutilizzo del codice. Se la funzione scambiaValori() la inserisci in un altro Playground con altri dati e valori, ti accorgerai che generà un errore perché il suo corpo sta utilizzando un riferimento ad una variabile che si trova fuori il suo mondo.

Infatti la variabile “primo”, come la var “secondo”, è stata inizializzata fuori dal corpo della funzione e per tanto non è assicurato che, in un altro progetto, la variabile da scambiare si chiamino “primo” e “secondo”.

Quindi ricordati di generalizzare i problemi e di non creare funzioni il cui corpo interagisce con il mondo esterno. L’unico modo per comunicare con il mondo esterno è utilizzare il return oppure i parametri inout.

Il motivo di tali scelte lo comprenderai meglio quando scoprirai la programmazione ad oggetti in Swift.

30
Q

Perché utilizzare le funzioni e consigli utili

A

Se vuoi diventare un buon programmatore leggi attentamente tutto quello che c’è scritto in questo paragrafo!

Utilizza nomi chiari per le tue funzione, già dal nome devi essere in grado capire a cosa serve. Per i parametri vale lo stesso principio.

Utilizza l’opzionalità. Rendere opzionale i parametri d’entrata o di uscita ti permette di poter gestire gli errori. Più avanti ne scoprirai altri e iniziarli a gestire fin da ora ti permetterà di diventare un buon programmatore.

Scrivi tutte le definizioni delle funzione in alto al codice del Playground. In questo modo dai ordine al tuo progetto.

Le funzioni permettono di generalizzare un problema. Inoltre con le funzioni ottimizzi i tempi sia di scrittura che di esecuzione del codice.

Le funzioni sono riutilizzabili in altri codici e in altri problemi. Imparare a scrivere funzioni quanto più generali possibile ti permetterà di poterle utilizzare in altri progetti senza doverle riscrivere nuovamente.

31
Q

Tabulare il codice

A

Esistono 2 tipi di programmatori:

func funzione() {

}

func funzione()

{

}

Quelli che vanno a capo all’apertura delle parentesi graffe e quelli che non lo fanno. Rispetta sempre e solamente una delle due! De gustibus no est disputandum, Io ad esempio utilizzo sempre la prima.

Se su questa regola posso anche chiudere un occhio, non posso farlo per quella sulla tabulazione del codice.

Per tabulazione si intende lo spazio lasciato dal margine laterale sinistro del foglio. La regola vuole che ad ogni apertura di parentesi graffe, il codice che è all’interno, deve essere tabulato di 4 spazi dall’inizio del foglio.

La tabulazione aumenta sempre di 4 se all’interno di un blocco ci sono più blocchi.

Un buon codice tabulato è il seguente:

func funzione() {

print(“riga tabulata con 4 spazi”)

if (1 < 2) {

print(“riga tabulata di 8 spazi”)

if(3 < 4) {

print(“riga tabulata di 12 spazi”)

}

}

print(“riga tabulata con 4 spazi”)

}

In questo modo sai sempre a quale blocco il codice si riferisce.

Tabulazione da ergastolo:

//DA NON IMITARE || IL MALE DEL MONDO

func funzione() {

print(“riga tabulata con 4 spazi”)

if (1 < 2) {

print(“riga tabulata di 8 spazi”)

if(3 < 4) {

print(“riga tabulata di 12 spazi”)

}

}

print(“riga tabulata con 4 spazi”)

}

32
Q

Istruzione guard in Swift. Un’istruzione di controllo sicura ed elegante

A

Chi non vorrebbe una guardia del corpo?

Le guardie servono per il controllo di qualcosa o qualcuno. Per il linguaggio Swift, quando si parla di controllo del codice si pensa immediatamente all’if else e allo switch. Sai che entrambi i sistemi sono efficientissimi e che permettono di eseguire delle porzioni di codice in base al verificarsi di una condizione.

E se ti dicessi che esiste una nuova istruzione di controllo e, per certi versi, migliore?

La nuova istruzione di controllo, che oggi ti introdurrò, si chiama guard ed offre un sistema veloce ed elegante per performare un’azione solo quando una condizione non è verificata. La sua sintassi è la seguente:

guard <condizione> else { <istruzioni> }</istruzioni></condizione>

E adesso mi dirai: a parte la sintassi dove sta la novità?

La particolarità dell’istruzione guard in Swift, sta nel fatto che, una volta che l’esecuzione del codice è entrata all’interno del blocco else, non si può più uscire se non con un’istruzione di trasferimento (break, return, continue, ecc.).

Questa clausola impone già un vincolo significativo.

L’istruzione guard può essere utilizzata solo all’interno delle funzione, dei cicli e delle altre componenti che vedrai più avanti (come classi e strutture). Di fatto non è un vincolo. Quando ti ritroverai, nel prossimo corso, a sviluppare la tua prima applicazione ti accorgerai che tutto il mondo gira grazie alle funzioni (e agli elementi delle prossime lezioni).

Mettiamoci subito all’opera e vediamo in cosa consiste l’istruzione guard con il linguaggio Swift!

33
Q

Istruzione Guard in Swift: imparare ad utilizzare la giusta istruzione di controllo

A

L’istruzione guard in Swift permette di performare un’azione solo quando la sua condizione non è verificata (ovvero è false).

Immagina d’aver creato una funzione per il controllo degli elementi presenti in un array. La funzione restituisce false, quindi esce dalla funzione, se non trova l’elemento intruso passato al parametro della funzione:

var array = [4, 6, 7, 11, -1, 44, 85]

func trovaIntruso(intruso: Int) -> Bool {

for elem in array {

guard elem != intruso else {

print(“Trovato l’elemento intruso (intruso) “)

return true

}

}

print(“Non ho trovato l’elemento (intruso)”)

return false

}

trovaIntruso(intruso: -1)

La funzione, al suo interno, esegue un ciclo for in che scorre gli elementi dell’array. L’istruzione guard controlla che l’elemento letto dal ciclo sia diverso da quello passato nel parametro intruso e, se lo è, l’esecuzione passa oltre.

Quando il ciclo troverà l’elemento “intruso“, nell’esempio è -1, la condizione dell’istruzione guard non sarà più verificata e l’esecuzione entrerà dentro il suo blocco else. Entrare dentro il blocco else, dell’istruzione guard, significa poterne uscire solo con un trasferimento (return, break, continue, ecc.).

Nel nostro caso, il blocco else, prima stampa dei messaggi d’avviso e poi esce dalla funzione ritornando true.

Puoi leggere l’istruzione guard del linguaggio swift in questa maniera: “Se la condizione non è verificata (guard) esegui quest’operazione (else)”.
Lo stesso esercizio con if-else:

func trovaIntruso(intruso: Int) -> Bool {

for elem in array {

if elem == intruso {

print(“trovato elemento intruso”)

print(“esco dalla funzione”)

return true

}

}

return false

}

34
Q

Optional Binding con l’istruzione guard in Swift

A

L’Optional Binding, introdotto nella lezione sull’opzionalità in Swift, è lo strumento utilizzato per estrapolare e controllare la presenza di un valore in una variabile opzionale.

Questo strumento è molto utilizzato dagli sviluppatori perché previene la nascita di errori derivati dalla non presenza di valore in una variabile opzionale.

Con l’istruzione guard in Swift è possibile eseguire l’optional binding in maniera decisamente più efficiente rispetto a quanto imparato a fare con l’istruzione if. Il principio è sempre lo stesso.

Nella condizione dell’istruzione si istanzia una costante con il valore delle variabile opzionale. La costante è in grado di estrapolare la parte reale della variabile opzionale:

var xCoding: String? = “xCoding.it”

func saluta(persona: String?) {

guard let nonOpzionale = persona else {

print(“Non hai esplicitato una persona”)

return

}

print(“Ciao (nonOpzionale) “)

}

saluta(persona: xCoding)

Una cosa importante, e che puoi notare dall’esempio, è che la costante definita dentro l’istruzione guard, può essere utilizzata anche all’esterno del suo blocco (cosa che con l’if-else non è permesso). Infatti la print finale stampa il contenuto della costante nonOpzionale.

Se adesso provassi a fare lo stesso esercizio con l’istruzione if-else, ti accorgeresti come la forma stilistica sia leggermente più confusionaria rispetto a quella creata con la keyword guard:

func saluta(persona: String?) {

if let nonOpzionale = persona {

print(“Ciao (nonOpzionale)”)

} else {

return

}

}

Quindi, già a prima vista, si nota facilmente come l’istruzione guard permette di scrivere codice in maniera più elegante.

Nel primo caso, anche non conoscendo il funzionamento dell’istruzione, si capisce che il compito finale della funzione è proprio quello di salutare qualcuno. Invece, nell’esempio dell’if-else non è facilmente deducibile perché il fine ultimo della funzione è contenuto all’interno del blocco if.

Ora per farti amare quest’istruzione, analizziamo un problema più complicato e che richiede un po’ di controlli per poter essere portato a compimento.

Esercizio 0. Crea la funzione che genera il codice fiscale unendo tre parametri d’ingresso (nome, cognome, età). La funzione restituisce il codice fiscale in uscita o nil nel caso d’errore.

func creaCodiceFiscale(nome: String?, cognome: String?, età: String?) -> String? {

guard let veroNome = nome else { return nil }

guard let veroCognome = cognome else { return nil }

guard let veraEtà = età else { return nil }

return(veroNome + veroCognome + veraEtà)

}

creaCodiceFiscale(nome: “Giuseppe”, cognome: “Sapienza”, età: “21”)

Tutte le istruzioni guard estrapolano il valore reale delle variabili utilizzando l’optional binding. Se qualcuna di queste non dovesse farlo perché il parametro è opzionale, si verrebbe catapultati fuori dalla funzione. Infine, se non ci sono stati problemi di binding, verrà restituito il codice fiscale.

Guarda invece cosa avresti scritto con l’istruzione if else.

Esercizio 1. Risolvi l’esercizo 0 con l’if else.

func creaCodiceFiscale(nome: String?, cognome: String?, età: String?) -> String? {

var veroNome: String

var veroCognome: String

var veraEtà: String

if let nomeNonOpt = nome {

veroNome = String(nomeNonOpt)

} else { return nil }

if let cognomeNonOpt = cognome {

veroCognome = String(cognomeNonOpt)

} else { return nil }

if let etàNonOpt = età {

veraEtà = String(etàNonOpt)

} else { return nil }

return(veroNome + veroCognome + veraEtà)

}

creaCodiceFiscale(nome: “Giuseppe”, cognome: “Sapienza”, età: “21”)