Funzioni Flashcards
Definire e richiamare le funzioni
Quando si definisce una funzione, è possibile definire opzionalmente uno o più nomi , i valori digitati che la funzione prende come input (noto come parametri), e / o un tipo di valore che la funzione restituirà come uscita (noto come tipo di ritorno).
Ogni funzione ha un nome, che descrive il compito che la funzione stessa deve eseguire. Per utilizzare una funzione, la funzione stessa deve essere “richiamata” e si devono passare ad essa valori di input (noto come argomenti), che corrispondono ai tipi di parametri della funzione.
La funzione nell’esempio qui sotto (greetingForPerson), ha un nome che descrive il “compito” della funzione stessa, cioè prendere il nome di una persona come input e restituire un messaggio di saluto per quella persona. Per fare questo, si definisce un parametro, un ingresso valore stringa denominato personName e un tipo di dato restituito (in questo caso String), che conterrà un messaggio di saluto per quella persona:
func sayHello(personName: String) -> String {<br></br>let greeting = “Hello, ” + personName + “!”<br></br>return greeting<br></br>}
Si indica il tipo di funzione di ritorno con la freccia ” ->” , che è seguito dal nome del tipo di dato restituito.
La definizione descrive ciò che la funzione fa, che cosa ci si aspetta di ricevere e quello che restituisce quando è terminata:
println(sayHello(“Anna”))<br></br>// prints “Hello, Anna!”<br></br>println(sayHello(“Brian”))<br></br>// prints “Hello, Brian!”
Si chiama la funzione sayHello passando un valore string tra parentesi, come sayHello (“Anna”). Poiché la funzione restituisce un valore String, sayHello può essere inclusa in una chiamata alla funzione println per stampare la stringa e vedere il suo valore di ritorno, come mostrato sopra.
Il corpo della funzione sayHello inizia definendo una nuova stringa costante e imposta a un semplice messaggio di saluto per personName. Questo saluto è poi passato nuovamente fuori la funzione utilizzando la parola chiave return. Appena saluto di ritorno viene chiamato, la funzione termina la sua esecuzione e restituisce il valore corrente di saluto.
È possibile chiamare la funzione sayHello più volte con valori di input diversi. L’esempio sopra mostra cosa succede se viene chiamato con un valore di ingresso di “Anna”, e un valore di ingresso “Brian”. La funzione restituisce un saluto su misura in ogni caso.
Per semplificare il corpo di questa funzione,si può procedere come segue:
“func sayHelloAgain(personName: String) -> String {<br></br>return “Hello again, ” + personName + “!”<br></br>}<br></br>println(sayHelloAgain(“Anna”))<br></br>// prints “Hello again, Anna!”
Parametri funzionali e valori di ritorno
In Swift i parametri di funzione e i valori di ritorno sono estremamente flessibili. È possibile definire qualsiasi cosa, da una semplice funzione di utilità con un unico parametro senza nome ad una funzione complessa con i nomi dei parametri espressivi e diverse opzioni per i parametri stessi.
Più parametri di input
Le funzioni possono avere più parametri di input, scritti fra parentesi nella funzione, separati da virgole.
Questa funzione richiede un inizio e un indice di fine per un intervallo semiaperto:
“func halfOpenRangeLength(start: Int, end: Int) -> Int {<br></br>return end – start<br></br>}<br></br>println(halfOpenRangeLength(1, 10))<br></br>// prints “9”
Funzioni senza parametri
Non si è tenuti a definire parametri di input per le funzioni. Eccone una senza parametri di input, che restituisce sempre lo stesso messaggio String ogni volta che viene chiamata:
func sayHelloWorld() -> String {<br></br>return “hello, world”<br></br>}<br></br>println(sayHelloWorld())<br></br>// prints “hello, world”
Funzioni senza valore di ritorno
La definizione di funzione ha ancora bisogno di parentesi dopo il nome, anche se non prende in input alcun parametro. Il nome della funzione è seguito anche da una coppia vuota di parentesi quando la funzione viene chiamata.
“
return end – start<br></br>}<br></br>println(halfOpenRangeLength(1, 10))<br></br>// prints “9”
Poichè non c’è bisogno di restituire un valore, la definizione della funzione non include la freccia di ritorno (->) o un tipo di ritorno.
“func printAndCount(stringToPrint: String) -> Int {<br></br>println(stringToPrint)<br></br>return countElements(stringToPrint)<br></br>}<br></br>func printWithoutCounting(stringToPrint: String) {<br></br>printAndCount(stringToPrint)<br></br>}<br></br>printAndCount(“hello, world”)<br></br>// prints “hello, world” and returns a value of 12<br></br>printWithoutCounting(“hello, world”)<br></br>// prints “hello, world” but does not return a value
La prima funzione, printAndCount, stampa una stringa, e poi restituisce il numero di caratteri come un int. La seconda funzione, printWithoutCounting, chiama la prima funzione, ma ignora il suo valore di ritorno. Quando la seconda funzione viene chiamata, il messaggio viene ancora stampato dalla prima funzione, ma il valore restituito non viene utilizzato.
Funzioni con più valori di ritorno
È possibile utilizzare un tipo di tupla come tipo di ritorno di una funzione per restituire più valori come parte del valore di ritorno.
L’esempio seguente definisce una funzione che conta il numero di vocali, consonanti, e altri caratteri in una stringa, in base al set standard di vocali e consonanti utilizzati in inglese:
func count(string: String) -> (vowels: Int, consonants: Int, others: Int) {<br></br>var vowels = 0, consonants = 0, others = 0<br></br>for character in string {<br></br>switch String(character).lowercaseString {<br></br>case “a”, “e”, “i”, “o”, “u”:<br></br>++vowels<br></br>case “b”, “c”, “d”, “f”, “g”, “h”, “j”, “k”, “l”, “m”,<br></br>“n”, “p”, “q”, “r”, “s”, “t”, “v”, “w”, “x”, “y”, “z”:<br></br>++consonants<br></br>default:<br></br>++others<br></br>}<br></br>}<br></br>return (vowels, consonants, others)<br></br>}
È possibile utilizzare questa funzione di conteggio per contare i caratteri in una stringa arbitraria, e per recuperare il totale di vocali e consonanti contate come una tupla di tre valori Int denominati:
let total = count(“some arbitrary string!”)<br></br>println(“(total.vowels) vowels and (total.consonants) consonants”)<br></br>// prints “6 vowels and 13 consonants”
Funzioni con più valori di ritorno
È possibile utilizzare un tipo di tupla come tipo di ritorno di una funzione per restituire più valori come parte del valore di ritorno.
L’esempio seguente definisce una funzione che conta il numero di vocali, consonanti, e altri caratteri in una stringa, in base al set standard di vocali e consonanti utilizzati in inglese:
func count(string: String) -> (vowels: Int, consonants: Int, others: Int) {<br></br>var vowels = 0, consonants = 0, others = 0<br></br>for character in string {<br></br>switch String(character).lowercaseString {<br></br>case “a”, “e”, “i”, “o”, “u”:<br></br>++vowels<br></br>case “b”, “c”, “d”, “f”, “g”, “h”, “j”, “k”, “l”, “m”,<br></br>“n”, “p”, “q”, “r”, “s”, “t”, “v”, “w”, “x”, “y”, “z”:<br></br>++consonants<br></br>default:<br></br>++others<br></br>}<br></br>}<br></br>return (vowels, consonants, others)<br></br>}
È possibile utilizzare questa funzione di conteggio per contare i caratteri in una stringa arbitraria, e per recuperare il totale di vocali e consonanti contate come una tupla di tre valori Int denominati:
let total = count(“some arbitrary string!”)<br></br>println(“(total.vowels) vowels and (total.consonants) consonants”)<br></br>// prints “6 vowels and 13 consonants”
Function Parameter Names
Tutte le funzioni di cui sopra definiscono i nomi dei parametri :
func someFunction(parameterName: Int) {<br></br>// function body goes here, and can use parameterName<br></br>// to refer to the argument value for that parameter<br></br>}
Tuttavia, questi nomi dei parametri sono utilizzati solo all’interno del corpo della funzione stessa, e non possono essere utilizzati quando si chiama la funzione. Questi tipi di nomi dei parametri sono noti come i nomi dei parametri locali, perché sono disponibili solo per l’uso all’interno del corpo della funzione.
Nomi dei parametri esterni
A volte è utile dare un nome ad ogni parametro quando si chiama una funzione.
Se si desidera che gli utenti che utilizzeranno le vostre funzioni forniscano i nomi dei parametri quando chiamano la funzione, definire un nome per ogni parametro esterno, in aggiunta al nome del parametro locale. Si scrive un nome di parametro esterno prima del nome del parametro locale , separati da uno spazio:
func someFunction(externalParameterName localParameterName: Int) {<br></br>// function body goes here, and can use localParameterName<br></br>// to refer to the argument value for that parameter<br></br>}
Si consideri la seguente funzione, che unisce due stringhe con l’inserimento di un terzo “joiner” tra di loro:
“func join(s1: String, s2: String, joiner: String) -> String {<br></br>return s1 + joiner + s2<br></br>}
Quando si chiama questa funzione, lo scopo dei tre parametri che vengono passati alla funzione non è chiaro:
join(“hello”, “world”, “, “)<br></br>// returns “hello, world”
Per rendere tutto più chiaro, definire i nomi dei parametri esterni:
func join(string s1: String, toString s2: String, withJoiner joiner: String)<br></br>-> String {<br></br>return s1 + joiner + s2<br></br>}
In questa versione della funzione join, il primo parametro ha un nome esterno di stringa e un nome locale di s1; il secondo parametro ha un nome esterno di toString e un nome locale di s2; e il terzo parametro ha un nome esterno di withJoiner e un nome locale di joiner.
È ora possibile utilizzare questi nomi di parametri esterni per chiamare la funzione in modo chiaro e inequivocabile:
“join(string: “hello”, toString: “world”, withJoiner: “, “)<br></br>// returns “hello, world”
Parametri per i nomi esterni
Se si desidera fornire un nome di parametro esterno per un parametro di una funzione, e il nome del parametro locale è già un nome appropriato da usare, non è necessario scrivere lo stesso nome due volte per quel parametro. Invece, scrivere il nome una volta, e apporre il simbolo cancelletto al parametro (#). Questo farà capire a Swift di usare quel nome come fosse il nome del parametro locale e il nome del parametro esterno.
Questo esempio definisce una funzione chiamata containsCharacter, che definisce i nomi dei parametri esterni per entrambi i parametri mettendo un # davanti ai loro nomi:
func containsCharacter(#string: String, #characterToFind: Character) -> Bool {<br></br>for character in string {<br></br>if character == characterToFind {<br></br>return true<br></br>}<br></br>}<br></br>return false<br></br>}
La scelta utilizzata per questa funzione elimina ogni ambiguità:
<sub>let containsAVee = containsCharacter(string: “aardvark”, characterToFind: “v”)<br>// containsAVee equals true, because “aardvark” contains a “v”</sub>
Valori dei parametri di default
È possibile definire un valore di default per ogni parametro come parte della definizione di una funzione. Se un valore di default è definito, è possibile omettere il parametro quando si chiama la funzione.
Ecco una versione della funzione join da prima, che fornisce un valore predefinito per il suo parametro joiner:
func join(string s1: String, toString s2: String,<br></br>withJoiner joiner: String = ” “) -> String {<br></br>return s1 + joiner + s2<br></br>}
Se un valore di stringa per joiner viene fornito quando la funzione join viene chiamata, il valore di stringa viene utilizzato in questo modo:
join(string: “hello”, toString: “world”, withJoiner: “-“)<br></br>// returns “hello-world”
Tuttavia, se nessun valore di joiner viene fornito quando la funzione viene chiamata, il valore predefinito di un unico spazio (“”) viene usato al posto:
“join(string: “hello”, toString: “world”)<br></br>// returns “hello world”
Nomi esterni per i parametri con valori di default
Nella maggior parte dei casi, è utile fornire un nome esterno per ogni parametro con un valore predefinito. Questo assicura che l’argomento per tale parametro sia chiaro nel momento in cui la funzione viene chiamata.
Per rendere questo processo più semplice, Swift fornisce un nome esterno automatico per qualsiasi parametro default che viene definito, se non si specifica un nome esterno da soli. Il nome esterno automatico è lo stesso del nome locale, come se si fosse apposto il cancelletto prima del nome locale nel codice.
Ecco una versione della funzione join di prima, che non prevede nomi esterni per uno qualsiasi dei suoi parametri, ma comunque fornisce un valore predefinito per il suo parametro joiner:
func join(s1: String, s2: String, joiner: String = ” “) -> String {<br></br>return s1 + joiner + s2<br></br>}
In questo caso, Swift fornisce automaticamente un nome di parametro esterno a joiner per il parametro default. Il nome esterno deve essere fornito quando si chiama la funzione, rendendo lo scopo del parametro chiaro e inequivocabile:
join(“hello”, “world”, joiner: “-“)<br></br>// returns “hello-world”
Un parametro variadic accetta zero o più valori di un tipo specificato. Si utilizza un parametro variadic per specificare che al parametro può essere passato un numero variabile di valori di ingresso quando la funzione viene chiamata.
I valori passati ad un parametro variadic sono resi disponibili all’interno del corpo della funzione come una matrice del tipo appropriato. Ad esempio, un parametro variadic con un nome numerico di tipo double è reso disponibile all’interno del corpo della funzione sotto forma di matrice costante di tipo double [].
L’esempio seguente calcola la media aritmetica (noto anche come media) per un elenco dei numeri di qualsiasi lunghezza:
func arithmeticMean(numbers: Double…) -> Double {<br></br>var total: Double = 0<br></br>for number in numbers {<br></br>total += number<br></br>}<br></br>return total / Double(numbers.count)<br></br>}<br></br>arithmeticMean(1, 2, 3, 4, 5)<br></br>// returns 3.0, which is the arithmetic mean of these five numbers<br></br>arithmeticMean(3, 8, 19)<br></br>// returns 10.0, which is the arithmetic mean of these three numbers
Parametri costanti e variabili
Parametri di funzione sono costanti per impostazione predefinita.
Tuttavia, a volte è utile per una funzione avere una copia variabile del valore di un parametro con cui lavorare.
Definire i parametri variabili anteponendo al nome del parametro con la parola chiave var:
“func alignRight(var string: String, count: Int, pad: Character) -> String {<br></br>let amountToPad = count – countElements(string)<br></br>for _ in 1…amountToPad {<br></br>string = pad + string<br></br>}<br></br>return string<br></br>}<br></br>let originalString = “hello”<br></br>let paddedString = alignRight(originalString, 10, “-“)<br></br>// paddedString is equal to “—–hello”<br></br>// originalString is still equal to “hello”
Parametri In-Out
I parametri variabili, come abbiamo visto, possono essere modificati solo all’interno della funzione stessa. Se si desidera modificare il valore di un parametro e che tali modifiche persistano dopo che la chiamata della funzione è terminata, bisogna definire il parametro come parametro in-out.
Si dichiara un parametro e si antepone “inout ” al suo inizio. Un parametro in-out ha un valore che viene passato alla funzione, viene modificato nella funzione, e viene restituito dalla funzione con il valore originale modificato.
È possibile passare solo una variabile come argomento per un parametro in-out. Non è possibile passare una costante o un valore literal come argomento, perché le costanti letterali e non possono essere modificate. Puoi piazzare una e commerciale (&) direttamente prima del nome di una variabile quando si passa come argomento di un parametro inout, per indicare che può essere modificato dalla funzione.
Ecco un esempio di una funzione chiamata swapTwoInts:
func swapTwoInts(inout a: Int, inout b: Int) {<br></br>let temporaryA = a<br></br>a = b<br></br>b = temporaryA<br></br>}
La funzione swapTwoInts scambia tra di loro i valori di a e b. La funzione esegue lo scambio memorizzando il valore di una in una costante temporanea denominata temporaryA, assegnando il valore di b per una, e assegnando temporaryA a b.
È possibile chiamare la funzione swapTwoInts con due variabili di tipo int per scambiare i loro valori. Si noti che i nomi di someInt e anotherInt sono precedute da una e commerciale quando sono passati alla funzione swapTwoInts:
var someInt = 3<br></br>var anotherInt = 107<br></br>swapTwoInts(&someInt, &anotherInt)<br></br>println(“someInt is now (someInt), and anotherInt is now (anotherInt)”)<br></br>// prints “someInt is now 107, and anotherInt is now 3”
L’esempio sopra mostra che i valori originali di someInt e anotherInt vengono modificati dalla funzione swapTwoInts, anche se essi sono stati inizialmente definiti al di fuori della funzione.
Tipi di funzione
Ogni funzione ha un tipo specifico, composto dai tipi di parametri e il tipo di ritorno della funzione.
Per esempio:
func addTwoInts(a: Int, b: Int) -> Int {<br></br>return a + b<br></br>}<br></br>func multiplyTwoInts(a: Int, b: Int) -> Int {<br></br>return a * b<br></br>}
Questo esempio definisce due semplici funzioni matematiche chiamate addTwoInts e multiplyTwoInts. Queste funzioni, ciascuna per due valori Int, restituiscono un valore int, che è il risultato di un’ operazione matematica.
Il tipo di entrambe queste funzioni è (Int, Int) -> Int. Questo può essere letto come:
“Un tipo di funzione che ha due parametri, di tipo Int, e che restituisce un valore di tipo int.”
Ecco un altro esempio, per una funzione senza parametri e valore di ritorno:
func printHelloWorld() {<br></br>println(“hello, world”)<br></br>}
Il tipo di questa funzione è () -> (), o “. Una funzione che non ha parametri, e restituisce Void”. Le funzioni che non specificano un valore di ritorno restituiscono sempre Void, che equivale a una tupla vuota, indicata come ().
Utilizzo dei tipi di funzione
È possibile utilizzare i tipi di funzione, proprio come qualsiasi altro tipo di Swift. Ad esempio, è possibile definire una costante o una variabile di un tipo di funzione e assegnare una funzione appropriata a tale variabile:
var mathFunction: (int, int) -> int = addTwoInts
Questo può essere letto come:
Definire una variabile chiamata mathFunction, che prende due valori Int e restituisce un valore Int. Impostare questa nuova variabile per fare riferimento alle addTwoInts della funzione chiamata.
La funzione addTwoInts ha lo stesso tipo di variabile mathFunction, e quindi questa assegnazione è consentita dal tipo stesso.
Ora è possibile chiamare la funzione assegnata con il nome mathFunction:
println(“Result: (mathFunction(2, 3))”)<br></br>// prints “Result: 5”
Una funzione diversa con lo stesso tipo di corrispondenza può essere assegnata alla stessa variabile, come per i tipi non-funzionali:
mathFunction = multiplyTwoInts<br></br>println(“Result: (mathFunction(2, 3))”)<br></br>// prints “Result: 6”
Come con qualsiasi altro tipo, si può lasciare a Swift il compito di dedurre il tipo quando si assegna una funzione ad una costante o variabile:
anotherMathFunction = addTwoInts<br></br>// AnotherMathFunction si deduce essere di tipo (int, int) -> int