Fonctions : compléments
Mémoïsation
💡 Idée : réduire le temps de calcul d'une fonction
❓ Comment : mise en cache des résultats → Au prochain appel avec mêmes arguments, renverra résultat en cache
👉 En pratique : fonction memoizeN de la librairie FSharpPlus
⚠️ Attention : Comme tout optimisation, à utiliser quand le besoin se fait sentir et en validant (mesurant) que cela marche sans désagrément annexe.
☝ Ne pas confondre avec expression lazy (slide suivante)
Lazy expression
Sucre syntaxique pour créer un objet .NET Lazy<'T> à partir d'une expression
→ Expression pas évaluée immédiatement mais qu'à la 1ère demande (Thunk)
→ Intéressant pour améliorer performance sans trop complexifier le code
let printAndForward x = printfn $"{x}"; x
let a = lazy (printAndForward "a")
let b = printAndForward "b"
// > b
printfn $"{a.Value} et {b}"
// > a
// > a et b
printfn $"{a.Value} et c"
// > a et cLazy active pattern
Lazy active patternExtrait la valeur dans un objet Lazy
Organisation des fonctions
3 façons d'organiser les fonctions = 3 endroits où les déclarer :
Module : fonction déclarée dans un module 📍 Module
Nested : fonction déclarée à l'intérieur d'une valeur / fonction
💡 Encapsuler des helpers utilisés juste localement
☝ Paramètres de la fonction chapeau accessibles à fonction nested
Method : fonction définie comme méthode dans un type (next slide)
Méthodes
Définies avec mot-clé
memberplutôt queletChoix du self-identifier :
this,me,_...Paramètres sont au choix :
Tuplifiés : style OOP
Curryfiés : style FP
Méthodes - Exemple
Fonction vs Méthode
Nommage
camelCase
PascalCase
Curryfication
✅ oui
✅ si ni tuplifiée, ni surchargée
Paramètres nommés
❌ non
✅ si tuplifiés
Paramètres optionnels
❌ non
✅ si tuplifiés
Surcharge / overload
❌ non
✅ si tuplifiés
Inférence des arguments → à la déclaration
➖ Possible
✅ oui, du this
➖ Possible pour les autres arguments
→ à l'usage
✅ oui
❌ non, il faut annoter le type de l'objet pour utiliser une de ses méthodes
En argument d'une high-order fn
✅ oui
❌ non, lambda nécessaire
Support du inline
✅ oui
✅ oui
Récursive
✅ si rec
✅ oui
How To: Pipeline avec une méthode d'instance ?
Exemple : comment "piper" la méthode ToLower() d'une string ?
Via lambda :
"MyString" |> (fun x -> x.ToLower())Idem via fonction nommée telle que :
String.toLowerde la librairie FSharpPlus"MyString" |> String.toLower
Alternative au pipeline : passer par une valeur intermédiaire :
→ let low = "MyString".ToLower()
Interop avec la BCL
BCL = Base Class Library .NET
Méthode void
Une méthode .NET void est vue en F# comme renvoyant unit.
Réciproquement, une fonction F# renvoyant unit est compilée en une méthode void.
Equivalent C# d'après SharpLab :
Appel à une méthode de la BCL à N arguments
Une méthode .NET avec plusieurs arguments est "pseudo-tuplifiée" :
Les arguments doivent tous être spécifiés (1)
L'application partielle des paramètres n'est pas supportée (2)
Les appels ne marche pas avec un vrai tuple F♯ ⚠️ (3)
💡 Note : on peut utiliser l'opérateur pipe |> pour appeler une méthode tuplifiée
→ Cf. Orienté-objet / Membres 📍
Paramètre out - En C♯
out - En C♯out utilisé pour avoir plusieurs valeurs en sortie
→ Ex : Int32.TryParse, Dictionary<,>.TryGetValue :
Paramètre out - En F♯
out - En F♯Possibilité de consommer la sortie sous forme de tuple 👍
💡 Fonctions F♯ tryXxx s'appuient plutôt sur le type Option<T> 📍
Instancier une classe avec new ?
new ?Appel d'une méthode surchargée
Compilateur peut ne pas comprendre quelle surcharge est appelée
Astuce : faire appel avec argument nommé
Mis à jour
Ce contenu vous a-t-il été utile ?