Bonjour les adorateurs de Swift, aujourd’hui je vais vous présenter les fonctions et leur fonctionnement (lol). Pour ceux qui ont leur gyrophare “Alerte mathématiques” qui s’est allumé, pas de panique, on ne va pas faire de maths, on va juste leur emprunter un concept qui va s’avérer tout aussi fondamental que les variables ou les conditions par exemple (et qui sont eux aussi emprunté au maths). Alors c’est parti !
A quoi ça sert ?
Les fonctions sont un moyen d’exécuter un morceau spécifique de code à volonté, et en fonction de certains paramètres. Elles permettent de regrouper certaines actions répétitives en une seule commande pour éviter d’avoir à réécrire tout le code. Par exemple imaginons que nous souhaitions réaliser un script de caisse enregistreuse de fruits et légumes (la classe !), on aurait besoin de quelque chose comme ça :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | // L'argent actuellement en caisse (type Int) var argent = 10 // Ce que l'on a en magasin (type dictionnaire [String: Int]) var stockFruits = ["pommes" : 10, "poires" : 10, "scoubidous" : 20] /* Le prix de chaque produit On défini ici le type de variable car il est nécessaire de le préciser pour les tests plus loin */ var prix:[String: Int] = ["pommes" : 2, "poires": 4, "scoubidous" : 1] // --- Vente d'une pomme --- /* On teste d'abord si le dictionnaire des stock contient bien l'index "pommes" et si c'est le cas, la valeur sera stockée dans la constante stock */ if let stock = stockFruits["pommes"] { // Si on a du stock if stock > 0 { // Si l'index "pommes" existe dans le dictionnaire prix if let prixAPayer = prix["pommes"] { // On ajoute le prix à payer dans l'argent de la caisse argent += prixAPayer // On enlève une pomme du stock stockFruits["pommes"] = stock - 1 } } } |
Même sans commentaires, ce code est plutôt long, et il est nécessaire de l’exécuter plusieurs fois si l’on souhaite vendre plus de produits, et il serait très long de tout réécrire à chaque fois. Cela augmenterai également le taux d’erreurs dans le code et diminuerai fortement sa lisibilité. il est donc possible de déclarer une fonction qui effectuera la vente en fonction du produit qu’on lui indiquera.
Anatomie d’une fonction
Une fonction se déclare avec le mot-clé func
suivi du nom de la fonction. Les noms de fonctions sont restreints aux même possibilités que les noms de variables. Accolé au nom s’en suivent des parenthèses contenant les paramètres passés à la fonction sous forme de constantes séparées par des virgules. Chaque constante doit être nommée et son type déclaré et elles seront accessibles dans la fonction. Puis le code a exécuter se situe entre accolades.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | var argent = 10 var stockFruits = ["pommes" : 10, "poires" : 10, "scoubidous" : 20] var prix:[String: Int] = ["pommes" : 2, "poires": 4, "scoubidous" : 1] func vendre(fruit:String) { if let stock = stockFruits[fruit] { if stock > 0 { if let prixAPayer = prix[fruit] { argent += prixAPayer stockFruits[fruit] = stock + 1 } } } } // Vente d'une pomme vendre(fruit: "pommes") // Vente d'une poire vendre(fruit: "poires") |
Ici, on déclare la fonction vendre()
qui accepte un paramètre : la variable (ou plutôt la constante) fruit de type String. Le code qu’exécute la fonction est exactement le même qu’auparavant en remplaçant l’index “pommes” par la valeur de la constante fruit passée en paramètre dans func vendre(fruit:String)
. On peut exécuter la fonction en l’appelant plus loin dans le code en changeant simplement la valeur du paramètre.
On peut déclarer plusieurs paramètres pour chaque fonction en les séparant par des virgules :
1 | func vendre(fruit: String, legume: String) |
La compilation des fonctions
Toutes les constantes déclarées dans la fonction doivent être présentes lors de l’appel ou bien Xcode retournera une erreur de compilation. Le code qui est exécuté dans les fonctions l’est de manière synchrone ce qui veut dire que le code écrit après l’appel de la fonction ne sera exécuté que lorsque la totalité du code la fonction se sera exécuté.
1 2 3 | print(argent) // 10 vendre(fruit: "pommes") print(argent) // 12 |
Les fonctions peuvent agir sur les variables externes et les modifier pour la totalité du reste du script. Il est même possible de déclarer les fonctions avant les variables qu’elles utilisent :
1 2 3 4 5 6 | func vendre(fruit:String) { // code } var argent = 10 vendre(fruit: "pommes") |
Il est en revanche impossible d’utiliser une fonction avant sa déclaration dans un code procédural, c’est à dire en dehors des classes en programmation orientée objet, ce à quoi nous viendrons plus tard.
Pour des raisons pratiques, il est possible de donner deux noms différents pour un même paramètre passé, un pour l’appel, et l’autre pour l’intérieur de la fonction. Les deux noms seront donc déclarés l’un après l’autre dans la fonction, le nom extérieur en premier. Par exemple on pourrait déclarer func vendre(nomExterieur nomInterieur:String)
; pour appeler cette fonction on utiliserai vendre(nomExterieur: "scoubidous")
, mais la variable contenant “scoubidous” à l’intérieur de la fonction s’appellera nomInterieur. On peut ainsi éviter d’avoir à entrer le nom de la variable dans l’appel de la fonction, en le remplaçant par un underscore (_) qui signifie “pas de nom de variable” en swift.
1 2 3 4 5 | func vendre(_ fruit:String) { // code } vendre("pommes") |
Les valeurs de retour
Une fonction peut retourner une valeur, qui sera alors stockée dans une variable. Il est nécessaire de définir le type de valeur qui sera retourné dans la déclaration de la fonction de cette façon :
1 2 3 4 5 | func vendre(_ fruit:String) -> Bool { return true } var vendu = vendre("pommes") // true |
Ici, on déclare avec -> Bool que la fonction retrournera une valeur de type boolean. Dans la fonction, on retourne ensuite la valeur souhaitée : true qui est ensuite stockée dans la variable “vendu”. Le code return permet d’effectuer le retour d’une valeur mais stoppe aussi l’exécution de la fonction. Aucun code ne pourra être exécuté après le return dans la fonction. Et puisque l’on a indiqué que la fonction retrournait une valeur, le return est obligatoire.
Par exemple, si on reprend le code pour la vente de tout à l’heure et que l’on souhaite y ajouter un retour indiquant si la vente s’est bien effectué, il faudra que le code exécute obligatoirement un return.
1 2 3 4 5 6 7 8 9 10 11 12 | func vendre(fruit:String) -> Bool { if let stock = stockFruits[fruit] { if stock > 0 { if let prixAPayer = prix[fruit] { argent += prixAPayer stockFruits[fruit] = stock + 1 return true } } } return false } |
On place un return false
à la fin de la fonction car si elle s’exécute jusque là, c’est qu’elle ne s’est pas arrêté au return true
et donc que fatalement, la vente n’a pas eu lieu. Il faut donc toujours penser à retourner une valeur par défaut si la fonctions contient plusieurs sorties (des return) différentes.
Bien ! Je crois qu’on a toutes les bases pour commencer à s’amuser un peu ! Si vous avez tout compris à ce chapitre vous pouvez être fier de vous car maintenant vous êtes capables de créer des programmes simples ! Et nous en ferons bientôt un …