Opérateurs
Opérateur
Est défini comme une fonction :
Opérateur unaire :
let (~symbols) = ...Opérateur binaire :
let (symbols) = ...Symbols = combinaison de
% & * + - . / < = > ? @ ^ | ! $
2 façons d'utiliser les opérateurs :
En tant qu'opérateur → infixe
1 + 2ou préfixe-1En tant que fonction → chars entre
():(+) 1 2≡1 + 2
Opérateurs standards
Également définis dans FSharp.Core
Opérateurs arithmétiques :
+,-...Opérateurs de pipeline
Opérateurs de composition
Opérateurs Pipe
Opérateurs binaires, placés entre une valeur simple et une fonction
Appliquent la valeur à la fonction = Passe la valeur en argument
Permettent d'éviter la mise entre parenthèses / précédence
∃ plusieurs pipes
Pipe right
|>: le pipe "classique"Pipe left
<|a.k.a. pipe inverséPipe right 2
||>Etc.
Opérateur Pipe right |>
|>Inverse l'ordre entre fonction et valeur : val |> fn ≡ fn val
Ordre naturel "sujet verbe", comme appel méthode d'un objet (
obj.M(x))Pipeline : enchaîner appels de fonctions, sans variable intermédiaire
Aide inférence d'objet. Exemple :
Opérateur Pipe left <|
<|fn <| expression ≡ fn (expression)
☝ Usage un peu moins courant que
|>✅ Avantage mineur : permet d'éviter des parenthèses
❌ Inconvénient majeur : se lit de droite à gauche → Inverse du sens lecture naturel en anglais et ordre exécution
Quid d'une expression telle que x |> fn <| y ❓
x |> fn <| y ❓Exécutée de gauche à droite : (x |> fn) <| y ≡ (fn x) <| y ≡ fn x y
En théorie : permettrait d'utiliser
fnen position infixéeEn pratique : difficile à lire à cause du double sens de lecture ❗
👉 Conseil : À ÉVITER
Opérateur Pipe right 2 ||>
||>(x, y) ||> fn ≡ fn x y
Pour passer 2 arguments à la fois, sous la forme d'un tuple
Usage peu fréquent mais pratique avec
foldpour passer la valeur initiale (seed) et la liste avant de définir la fonctionfolder.
☝️ Cet opérateur correspond à la notion de "décurryfication" c'est-à-dire à pouvoir appeler une fonction f curryfiée en lui passant ces 2 paramètres sous la forme d'un tuple :
Opérateur Compose >>
>>Opérateurs binaires, placés entre deux fonctions → Le résultat de la 1ère fonction servira d'argument à la 2e fonction
f >> g ≡ fun x -> g (f x) ≡ fun x -> x |> f |> g
💡 Peut se lire « f ensuite g »
⚠️️ Les types doivent correspondre : f: 'T -> 'U et g: 'U -> 'V → On obtient une fonction de signature 'T -> 'V
Opérateur Compose inverse <<
<<Sert rarement, sauf pour retrouver un ordre naturel des termes
Exemple avec opérateur not (qui remplace le ! du C♯) :
Pipe |> ou Compose >> ?
|> ou Compose >> ?Compose let h = f >> g
Composition de 2 fonctions
fetgRenvoie une nouvelle fonction
Les fonctions
fetgne sont exécutées que lorsquehl'est
Pipe let result = value |> f
Juste une syntaxe différente pour passer un argument
La fonction
fest :Exécutée si elle n'a qu'1! param →
resultest une valeurAppliquée partiellement sinon →
resultest une fonction
Style Point-free
A.k.a Programmation tacite
Fonction définie par composition ou application partielle ou avec function
→ Paramètre implicite
(point fait référence à un point dans un espace)
💡 Conseil : l'expression anglaise Point-free est trompeuse en français car le terme Point désigne un point dans l'espace et non pas le point pour accéder à un membre d'un objet :
obj.Memberqui correspond à dot en Anglais. Mieux vaut employer Programmation tacite.
Pros/Cons ⚖️
✅ Avantages
Style concis • Abstraction des paramètres, opère au niveau fonctions
❌ Inconvénients
Perd le nom du paramètre devenu implicite dans la signature → Sans importance si la fonction reste compréhensible :
Nom du param non significatif (ex.
x)Type du param et nom de la fonction suffisent → Déconseillé pour une API publique
Limite 🛑
Marche mal avec fonctions génériques :
Opérateurs personnalisés
2 possibilités :
Surcharge d'opérateurs
Création d'un nouvel opérateur
Surcharge d'opérateurs
En général, concerne un type spécifique → Surcharge définie à l'intérieur du type associé (comme en C♯)
Création d'un nouvel opérateur
Définition plutôt dans un module ou dans un type associé
Cas d'usage classique : alias fonction existante, utilisé en infixe
Symboles autorisés dans un opérateur
Opérateur unaire "tilde"
→ ~ suivi de +, -, +., -., %, %%, &, &&
Opérateur unaire "snake"
→ Plusieurs ~, ex : ~~~~
Opérateur unaire "bang"
→ ! suivi combinaison de !, %, &, *, +, ., /, <, =, >, @, ^, |, ~, ?
→ Sauf != (!=) qui est binaire
Opérateur binaire
→ Toute combinaison de !, %, &, *, +, ., /, <, =, >, @, ^, |, ~, ?
→ qui ne correspond pas à un opérateur unaire
Symboles à l'usage
Tout opérateur s'utilise tel quel ❗ Sauf opérateur unaire "tilde" : s'utilise sans le ~ initial
Unaire tilde
let (~&&) x = …
&&x
Unaire snake
let (~~~) x = …
~~~x
Unaire bang
let (!!!) x = …
!!!x
Binaire
let (<ˆ>) x y = …
x <ˆ> y
☝ Pour définir un opérateur commençant ou terminant par un *, il faut mettre un espace entre ( et * ainsi qu'entre * et ) pour distinguer d'un bloc de commentaires F# (* *)
→ let ( *+ ) x y = x * y + y ✅
Opérateur ou fonction ?
Opérateur infixe vs fonction
👍 Pour :
Respecte l'ordre naturel de lecture (gauche → droite)
Permet d'éviter des parenthèses →
1 + 2 * 3vsmultiply (add 1 2) 3
⚠️ Contre :
Un opérateur "folklorique" (ex :
@!) sera moins compréhensible qu'une fonction dont le nom utilise le langage du domaine
Utiliser un opérateur en tant que fonction
💡 On peut utiliser l'application partielle d'un opérateur binaire :
Exemples :
A la place d'une lambda : →
(+) 1≡fun x -> x + 1Pour définir une nouvelle fonction : →
let isPositive = (<) 0≡let isPositive x = 0 < x≡x >= 0
Last updated
Was this helpful?