Explorer les fonctions
En règle générale, vous trouverez que votre code est répétitif. Il fait la même chose à divers endroits ou avec de légères différences. En pareil cas, réfléchissez à une façon de rendre le code réutilisable. Le moyen de faire face à cette situation est d’extraire ces expressions et de créer une ou plusieurs fonctions. Une fonction est un bloc de construction de base dans de nombreux langages de programmation, et F# ne fait pas exception.
Une fonction
Une fonction est une référence nommée constituée d’un corps composé d’une ou plusieurs expressions. Elle peut aussi contenir des paramètres. Une fonction commence par le mot clé let et le nom de la fonction. Il y a ensuite un opérateur d’affectation, et à droite de cet opérateur se trouve le corps de la fonction.
Voici la syntaxe d’une fonction :
let <function name> <parameters> = <function body>
Une fonction réelle, avec l’exemple de syntaxe précédent, se présente comme ceci :
let add a b = a + b
Dans cet exemple, le nom de la fonction est add et les paramètres sont a et b . Le corps de la fonction ajoute les deux paramètres ensemble, a+b, et retourne le résultat.
Valeurs de retour
Comme vous avez pu le constater dans le premier exemple, il n’y a pas de mot clé return pour préciser ce qui est retourné. En F#, ce qui est retourné est indiqué dans la dernière ligne d’une fonction. Penchez-vous sur cette fonction multiligne :
let addAndMultiply a b c =
let sum = a + b
let product = sum * c
product
La présence de product sur la dernière ligne vous indique ce qui est retourné. Maintenant, voyons comment appeler une fonction de ce type.
Appeler une fonction
Pour appeler (ou invoquer) une fonction, utilisez le nom de la fonction et ajoutez les paramètres que vous souhaitez utiliser en les séparant par un espace. Par exemple, pour appeler la fonction addAndMultiply(), entrez le code suivant :
addAndMultiply 2 3 3 // 15
Pour afficher les résultats de la fonction, vous pouvez l’affecter à une variable ou l’imprimer directement, comme ceci :
let sum = addAndMultiply 2 3 3
printfn "%i" sum
// OR
printfn "%i" (addAndMultiply 2 3 3)
Types déduits
Prenons le code suivant :
let add a b = a + b
let sum = add 2 2
let concat = add "hello" "world" // will give compilation error
Ce code échoue sur la dernière ligne avec le message suivant :
error FS0001: This expression was expected to have type
'int'
but here has type
'string'
Cet échec s’explique par le fait que F# avait déjà déterminé le type de paramètre qu’il fallait utiliser, en l’occurrence « integer » (entier). S’il s’est décidé sur le type entier, c’est en raison de l’information figurant dans la deuxième ligne, let sum = add 2 2. La fonction add() a été utilisée d’une manière qui indiquait que le paramètre était assurément de type entier.
Si la deuxième ligne n’avait pas existé, votre code aurait fonctionné :
let add a b = a + b
// let sum = add 2 2
let concat = add "hello" "world" // will work
Le compilateur voit que la première utilisation de la fonction se fait avec des chaînes et en conclut que le paramètre est de type chaîne. Par conséquent, le contexte et la première utilisation infèrent le type.
Types explicites
Il existe des situations où vous souhaitez être explicite, à la fois sur le type des paramètres et sur ce que la fonction retourne. Cela permet d’améliorer la lisibilité, même si le compilateur n’en a probablement pas besoin.
À titre d’exemple, penchons-nous sur la fonction suivante :
let convert a =
int a
Pour y ajouter des types, vous devez ajouter :<type>, comme ceci :
let convert (a:string) =
int a
Le paramètre prend maintenant le type string via le code let convert (a:string). Vous pouvez maintenant être encore plus explicite en ajoutant un type de retour. Pour ce faire, ajoutez un autre :<type> juste après votre paramètre :
let convert (a:string) :int =
int a
À présent, des parenthèses entourent le paramètre, comme dans (a:string). Le type de retour correspond à la dernière annotation :<type>, à savoir :int. F# est suffisamment intelligent pour gérer la plupart des scénarios, mais il est parfois nécessaire d’aider le code en étant plus explicite. L’ajout de types présente un autre avantage : il permet à un autre développeur de déterminer plus facilement ce qui se passe.