F# 10 est désormais disponible avec .NET 10 et Visual Studio 2026. Cette version est une version améliorée axée sur la clarté, la cohérence et les performances, apportant des améliorations modestes mais significatives qui rendent votre code quotidien plus lisible et plus robuste. Avec F# 10, Microsoft poursuit sa démarche visant à simplifier le langage et à améliorer ses performances.F# est un langage de programmation fonctionnel, impératif et orienté objet pour la plate-forme .NET. F# est développé par Microsoft Research et son noyau est dérivé du langage OCaml, avec lequel il est fortement compatible. Ces deux langages de programmation font partie de la même famille que les langages ML. Ce langage a été conçu spécifiquement pour la plate-forme .NET, donc fortement orienté-objet. Depuis novembre 2010, Microsoft a mis à la disposition de tous les bibliothèques core et son compilateur F#, sous la licence Apache 2.
Récemment, Microsoft a annoncé la dernière version de son framework logiciel .NET 10, apportant des améliorations au compilateur JIT, des améliorations NativeAOT, ainsi que l'optimisation du runtime. Il s'agit d'une version à support à long terme (LTS) qui devrait recevoir des mises à jour jusqu'en novembre 2028. Selon Microsoft, .NET 10 est la version la plus productive, moderne, sécurisée, intelligente et performante de .NET à ce jour.
F# 10 est désormais disponible avec .NET 10 et Visual Studio 2026. Cette version est une version améliorée axée sur la clarté, la cohérence et les performances, apportant des améliorations modestes mais significatives qui rendent votre code quotidien plus lisible et plus robuste.
Avec F# 10, Microsoft poursuit sa démarche visant à simplifier le langage et à améliorer ses performances. Les principales améliorations ergonomiques comprennent la suppression des avertissements dans un certain périmètre, une syntaxe plus cohérente pour les expressions de calcul et une meilleure prise en charge des accesseurs de propriétés automatiques. Cette version comprend également une mise à niveau de l'infrastructure afin d'accélérer la compilation et les outils interactifs sous la forme d'un nouveau cache de subsomption de types.
Améliorations du langage
1. Suppression des avertissements dans une portée donnée
La première fonctionnalité que je souhaite présenter pour F# 10 est très demandée : la possibilité de supprimer les avertissements dans des sections de code arbitraires. Le compilateur prend désormais en charge la directive #warnon, qui s'associe à #nowarn pour activer ou désactiver les avertissements dans une plage de code spécifique.
Un exemple :
| Code F# : | Sélectionner tout |
1 2 3 | // We know f is never called with a None. let f (Some a) = // creates warning 25, which we want to suppress // 2000 loc, where the incomplete match warning is beneficial |
Il est possible d'ajouter une directive #nowarn 25 juste au-dessus de la définition de la fonction, mais sans une directive #warnon 25 correspondante, cela désactivera l'avertissement FS0025 dans le reste du fichier, risquant ainsi de supprimer des problèmes légitimes ailleurs.
Avec F# 10, vous pouvez délimiter explicitement la section, en appliquant la suppression des avertissements à une portée aussi étroite qu'une seule ligne :
| Code F# : | Sélectionner tout |
1 2 3 4 | #nowarn 25 let f (Some x) = // FS0025 suppressed #warnon 25 // FS0025 enabled again |
À l'inverse, si un avertissement est désactivé globalement (par exemple, via un indicateur du compilateur), vous pouvez l'activer localement avec #warnon. Cette directive s'appliquera alors jusqu'à ce qu'une directive #nowarn correspondante soit rencontrée ou jusqu'à la fin du fichier.
Compatibilité :
Cette fonctionnalité s'accompagne de plusieurs modifications qui améliorent la cohérence des directives #nowarn/#warnon, ce qui se traduit par un comportement plus prévisible. Cependant, il s'agit de modifications importantes qui pourraient affecter votre base de code lorsque vous passerez à F# 10. Voici quelques exemples parmi les plus susceptibles de se produire :
- Les directives d'avertissement multilignes et vides ne sont plus autorisées.
- Les espaces entre # et nowarn ne sont plus autorisés.
- Les chaînes à triple guillemet, interpolées ou littérales ne peuvent pas être utilisées pour les numéros d'avertissement.
Le comportement des scripts est également affecté. Dans les versions précédentes, une directive #nowarn placée n'importe où dans un script s'appliquait à l'ensemble de la compilation. Désormais, son comportement dans les scripts correspond à celui des fichiers .fs, s'appliquant uniquement jusqu'à la fin du fichier ou jusqu'à une directive #warnon correspondante.
2. Modificateurs d'accès sur les accesseurs de propriétés automatiques
Un modèle fréquent dans la programmation orientée objet consiste à créer un état lisible publiquement mais modifiable en privé. Avant F# 10, pour y parvenir, il fallait utiliser une syntaxe de propriété explicite avec des champs de support, ce qui ajoutait beaucoup de code standard :
| Code F# : | Sélectionner tout |
1 2 3 | type Ledger() = [<DefaultValue>] val mutable private _Balance: decimal member this.Balance with public get() = this._Balance and private set v = this._Balance <- v |
Avec F# 10, vous pouvez appliquer des modificateurs d'accès distincts à des accesseurs de propriétés individuels. Cela vous permet de spécifier différents niveaux d'accès pour le getter et le setter d'une propriété en ligne, ce qui permet d'utiliser des modèles courants tels que des états lisibles publiquement mais modifiables en privé sans code standard verbeux.
Vous pouvez désormais réécrire ce qui précède comme suit :
| Code F# : | Sélectionner tout |
1 2 | type Ledger() = member val Balance = 0m with public get, private set |
À noter :
Vous pouvez placer un modificateur d'accès soit avant le nom de la propriété (s'appliquant aux deux accesseurs), soit avant les accesseurs individuels, mais pas les deux simultanément.
De plus, cette fonctionnalité ne s'étend pas aux fichiers de signature (.fsi). La signature correcte pour l'exemple Ledger ci-dessus serait :
| Code F# : | Sélectionner tout |
1 2 3 | type Ledger() = member Balance : decimal member private Balance : decimal with set |
3. Paramètres facultatifs ValueOption
Les paramètres facultatifs peuvent désormais utiliser une représentation ValueOption<'T> basée sur une structure. En appliquant l'attribut [<Struct>] à un paramètre facultatif, vous pouvez demander au compilateur d'utiliser ValueOption<'T> au lieu du type option basé sur une référence. Cela évite une allocation de mémoire pour le wrapper d'option, ce qui est avantageux dans le code où les performances sont critiques.
Les versions précédentes de F# utilisaient toujours le type option alloué dans le tas pour les paramètres facultatifs, même lorsque le paramètre était absent. Dans les scénarios à haut débit ou la création d'objets en boucle interne, cela imposait une pression inutile sur le GC. Les développeurs travaillant sur du code sensible aux performances n'avaient aucun moyen d'éviter ces allocations :
| Code F# : | Sélectionner tout |
1 2 3 4 5 6 | // Prior to F# 10: always uses reference option type X() = static member M(?x : string) = match x with | Some v -> printfn "Some %s" v | None -> printfn "None" |
Vous pouvez désormais utiliser l'attribut [<Struct>] sur un paramètre facultatif pour tirer parti de ValueOption basé sur une structure et éliminer les allocations lorsque l'argument est absent :
| Code F# : | Sélectionner tout |
1 2 3 4 5 | type X() = static member M([<Struct>] ?x : string) = match x with | ValueSome v -> printfn "ValueSome %s" v | ValueNone -> printfn "ValueNone" |
Choisissez cette option basée sur une structure pour les petites valeurs ou les types fréquemment construits où la pression d'allocation est importante. Utilisez option par défaut basée sur les références lorsque vous vous appuyez sur des aides de correspondance de modèles existantes, que vous avez besoin d'une sémantique de référence ou lorsque la différence de performances est négligeable. Cette fonctionnalité renforce la parité avec d'autres constructions du langage F# qui prennent déjà en charge ValueOption.
4. Prise en charge des appels en queue dans les expressions de calcul
Les constructeurs d'expressions de calcul (par exemple, les coroutines ou autres constructeurs implémentés avec des machines à états reprenables) peuvent désormais opter pour des optimisations d'appels en queue. Lors du désucrage, le compilateur reconnaît lorsqu'une expression telle que return!, yield! ou do! apparaît en position de queue et, lorsque le constructeur fournit des méthodes spéciales, achemine ces appels vers les points d'entrée optimisés.
Si un générateur implémente :
- ReturnFromFinal, le compilateur l'appellera pour un return! en queue (en revenant à ReturnFrom si la variante finale est absente).
- YieldFromFinal, le compilateur l'appellera pour un yield! en queue (en revenant à YieldFrom s'il est absent).
- Pour un do! terminal, le compilateur préférera ReturnFromFinal, puis YieldFromFinal, avant de revenir à la voie Bind normale.
Ces membres *Final sont facultatifs et existent uniquement pour permettre l'optimisation : ils permettent aux constructeurs de court-circuiter les continuations ou de renoncer prématurément aux ressources. Les constructeurs qui ne fournissent pas ces membres conservent leur sémantique existante inchangée.
Exemples :...
La fin de cet article est réservée aux abonnés. Soutenez le Club Developpez.com en prenant un abonnement pour que nous puissions continuer à vous proposer des publications.