Compatibile con Xcode 8

Le funzioni in Swift. Definizione e chiamata di una funzione

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!

Il paradigma di programmazione Divide et Impera

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

Fin da scuola sei stato abituato a risolvere un problema step by stepOvvero 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.

Le funzioni in Swift

Definire, creare e utilizzare una funzione con il linguaggio Swift

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:

1# Definire una funzione

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 prototipodefinizione della funzioneOvvero, 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.

2# Creare il corpo della funzione

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:

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.

3# Chiamare una funzione

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:

chiamata di una funzione in swift

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ì:

Funzioni linguaggio swift. Corpo e chiamata

Definire i parametri in ingresso della funzione

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:

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

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


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:

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

Esercizi da svolgere

Prima di procedere oltre, prova a risolvere questi esercizi.

  • Esercizio 1. Dato un dizionario di studenti del tipo [String, String] dove la chiave è il nome dello studente ed il valore rappresenta il loro sesso (quindi “M” o “F”), crea una funzione che stampi in console il numero dei soli studenti “M”.
    • Usa il seguente dizionario come esempio: [“Giuseppe Sapienza” : “M”, “Delia Leone” : “F”, “Luca Pappalardo” : “M”].
    • In base al dizionario che hai visto sopra, la funzione deve stampare in console: “nella classe ci sono 2 Maschi”.
  • Esercizio 2. Crea una funzione che, dato un array di Int in ingresso, stampi il numero di elementi presenti nell’array. Cioè, se nella funzioni passi l’array [4,5,6] la funzione deve stampare in console: “nell’array ci sono 3 elementi”.
  • Esercizio 3. Crea una funzione che, dato un numero in ingresso, stampi il suo negativo. Cioè se nella funzione inserisci 1 devi stampare -1. Se invece inserisci un numero negativo, questo deve diventare positivo.

condividi xcoding

Sei a metà di un lunghissimo tutorial. In questi casi ti consiglio di prenderti una pausa di almeno 10 minuti, nel frattempo fai una partita a League of Legends, cazzeggia, esci fuori, fai un po’ quello che vuoi ma se inizi ad essere confuso non continuare con il tutorial.

Nel frattempo che fai una pausa sarei davvero felice se contribuissi al mio progetto semplicemente mettendo un mi piace o follow alle mie pagine.

[addtoany]

Grazie davvero :-)

Funzioni con più parametri in ingresso

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.

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

funzioni-linguaggio-swift-con-piu-parametri

Tipo di dato d’uscita o return di una funzione

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:

parametri-funzioni-linguaggio-swift

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:

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.

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.

Esercizio 5 (da svolgere). Scrivi la funzione che calcola la metà di un numero (se non riesci a svolgerlo ripeti dall’inizio tutti i paragrafi oppure scrivi un commento alla lezione).

Funzioni senza valore di ritorno

Le funzione 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:

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.

Parametri d’uscita multipli

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:

Parametri di ingresso e uscita opzionali

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.

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:

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

funzioni linguaggio swift consigli utili

Parametro Inout

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:

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:

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

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.

parametro-inout-linguaggio-swift

Un problema filosofico

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

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.

Perché utilizzare le funzioni e consigli utili

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.

Tabulare il codice

Esistono 2 tipi di programmatori:

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 foglioLa 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:

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

Tabulazione da ergastolo

 

Considerazioni ed Esercizi

Esistono altre linee guida da seguire e dato che stai imparando a programmare con me, le apprenderai strada facendo.

Esercizi lezione non svolti

  • Esercizio 8. Una funzione permette di controllare la presenza o meno del prefisso internazionale in una stringa che rappresenta un numero. La funzione deve avere come parametri il numero da controllare ed il prefisso nazionale che deve avere.
    • Per esempio. Se il numero in ingresso è “+39 3491234567” ed il prefisso che deve possedere è “+39”, la funzione deve restituire in uscita il messaggio: “il numero è Italiano”.
    • Prevedi anche i casi d’errore (il prefisso non è corretto, valori opzionali).
    • Ti ricordo che per leggere i caratteri singolarmente di una stringa devi utilizzare il .characters. C’è un trucchetto per risolvere questo esercizio che ti posso svelare solo se lasci un commento :P
  • Esercizio 9. Scrivi la funzione che calcoli la media aritmetica dei valori contenuti in un Array. La funzione ritorna il valore calcolato.

Ti vuoi mettere alla prova? Prova a superare la sfida del soldato swift!

Buona Programmazione!

Changelog

  • 31/10/2016 – Aggiunti i paragrafi: Parametro inout e Un problema filosofico.
  • 15/10/2016 – Aggiunto il changelog. Modifica generale del testo. Tutorial compatibile con Xcode 8 e linguaggio Swift 3.0.

Torna a: Corso gratuito linguaggio di programmazione Swift > Dai controlli alle funzioni del linguaggio Swift

Start typing and press Enter to search

While e Switch in SwiftProgrammazione ad oggetti in Swift