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 + 2
ou préfixe-1
En 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
fn
en 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
fold
pour 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
»
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
f
etg
Renvoie une nouvelle fonction
Les fonctions
f
etg
ne sont exécutées que lorsqueh
l'est
Pipe let result = value |> f
Juste une syntaxe différente pour passer un argument
La fonction
f
est :Exécutée si elle n'a qu'1! param →
result
est une valeurAppliquée partiellement sinon →
result
est 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.Member
qui 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 * 3
vsmultiply (add 1 2) 3
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 + 1
Pour définir une nouvelle fonction : →
let isPositive = (<) 0
≡let isPositive x = 0 < x
≡x >= 0
Dernière mise à jour
Cet article vous a-t-il été utile ?