Bien que les nouvelles récentes se soient en grande partie focalisées sur C# et Windows 10, F# n’est pas en reste. En effet, la dernière version de F# 4.0 est embarquée avec Visual Studio 2015 RC. La première chose à noter, c’est que ces derniers travaux sont réellement le fruit de la communauté. Des 38 contributeurs, seul un quart a une quelconque affiliation avec Microsoft. Tout le travail a été réalisé de façon ouverte à travers le site GitHub de F#, site qui a également vocation à recueillir les divers feedbacks. La release apporte de nombreux changements, autant au langage et au runtime qu’à l’IDE. Cet article en présente les éléments phares ; la liste complète peut être consultée sur le blog F#.
Métaprogrammation
La métaprogrammation en .NET, via les arbres d’expression (expression trees), est une fonctionnalité très importante depuis l’introduction de LINQ avec .NET 4.0. Avec F# 4.0, le travail avec les arbres d’expression devient encore plus simple. En positionnant l’attribut ReflectedDefinition sur un argument de type FSharp.Quotations.Expr, l’emplacement d’appel bascule automatiquement en sémantique "call-by-name". Auparavant, il était nécessaire d’annoter les expressions à l’appel, comme l’illustrent les 2 premières lignes ci-dessous. La troisième montre comment le bruit correspondant à la citation explicite des expressions est éliminé, ce qui participe à faciliter le travail avec les librairies s’appuyant sur la métaprogrammation.
Test.Expression1 ( <@ x + 1 @> ) //typed expression
Test.Expression2 ( <@@ x + 1 @@> ) //untyped expression
Test.Expression3 ( x + 1 ) //typed expression with ReflectedDefinition attribute
Amélioration des directives de preprocessing
Jusqu’à maintenant, F# bénéficiait d’un support que très limité des directives de preprocessing. Les opérations booléennes telles que “#if TRACE || DEBUG” n’étaient pas possibles jusqu’à cette nouvelle version, un contournement pour F# 3 et les versions précédentes consistait à utiliser des #if imbriqués pour simuler des "et" et à dupliquer le code pour le "ou".
Unités de mesure
Lorsque l’on travaille sur des applications scientifiques ou d’ingénierie, des erreurs peuvent souvent être liées aux unités de mesure. Par exemple, vous pouvez avoir une mesure en pouces et une autre en mètres. En 1999, ce genre d’erreur a causé la perte de Mars Orbiter, une sonde spatiale à 125 millions de dollars. F# élimine cette classe d’anomalies avec le concept d’unités de mesure. Les valeurs scalaires peuvent devenir des mesures en leur ajoutant des suffixes comme "<cm>" ou "<miles/hour>". Comme le montre la ligne suivante, même les conversions entre unités sont exprimées en termes d’unités de mesure.
let cmPerInch : float<cm/inch> = 2.54<cm/inch>
Ce qu’apporte F# 4, c’est la possibilité d’utiliser des exposants fractionnels dans l’expression d’une unité de mesure, par exemple :
[<Measure>] type Jones = cm Hz^(1/2) / W
Héritage de types avec de multiples interfaces génériques
Ce point est délicat à comprendre si vous n’êtes pas familier avec F# et fait référence à une frustration si vous l’êtes. Pour commencer, prenons une classe qui représente des nombres hexadécimaux. En C#, vous pourriez concevoir cette classe de sorte qu’elle soit comparable à la fois à des chaînes de caractères et à des entiers.
public class Hexidecimal : IComparable<string>, IComparable<int>
À cause de la nature complexe de l’inférence de type de F#, il était auparavant impossible d’exprimer cette classe en F#. Non seulement vous ne pouviez pas définir un type avec de multiples interfaces qui diffèrent uniquement par leur argument de type, mais vous ne pouviez pas hériter d’un type comme celui-ci non plus. F# 4 ne résout pas complètement ce problème mais propose un contournement. Vous pouvez maintenant créer deux classes, une pour chaque interface, et faire hériter la seconde de la première. Le code reste un peu fastidieux mais cela est nécessaire à l’occasion lorsque l’on travaille avec des librairies C#.
Propriétés d’extension dans les initialiseurs d’objets
Les propriétés d’extension, fortement plébiscitées pour C#, sont déjà disponibles en F#. Cette release ajoute la possibilité des les utiliser dans des initialiseurs d’objets.
Suppression de la marque Microsoft
Conformément à une tradition datant de Visual Basic 7, les namespaces spécifiques au langage F# commencent tous par "Microsoft.FSharp". F# étant à présent plus conduit par la communauté que propriété de Microsoft, ceci n’est plus approprié et la marque Microsoft peut être éliminée. Ainsi, pour rendre le code de F# neutre par rapport à l’éditeur (et aux plateformes), le préfixe "Microsoft." peut à présent être optionnellement omis lorsque l’on fait référence à des namespaces, des modules et des types de FSharp.Core.
Amélioration des performances : comparaisons non-structurelles
Par défaut, F# s’appuie sur des comparaisons structurelles plutôt que sur les opérateurs natifs fournis par les types, comme op_Equality. Si cela facilite les comparaisons de données complexes, la performance peut en souffrir. Lorsque vous recherchez la performance ou la sémantique des opérateurs de comparaison natifs, vous pouvez maintenant utiliser "open NonStructuralComparison" pour changer le comportement des opérateurs comme =. Un benchmark simple consistant à faire des comparaisons d’objets DateTime en boucle montre des améliorations de plus d’un ordre de grandeur.
Debugging des scripts
Avant VS 2015, les développeurs F# devaient choisir entre le mode interactif et l’accès complet au debugger. Ils peuvent maintenant cliquer sur un script pour le lancer en mode debug et ainsi bénéficier du meilleur des deux mondes.
Rebuilds intelligents
Avant VS 2015, Visual Studio n’était pas capable de détecter qu’un projet F# avait besoin d’être compilé. Tous les projets F# étaient donc systématiquement recompilés, même lorsque rien n’avait changé. Les développeurs n’ont à présent plus besoin d’attendre inutilement des projets compilés pour rien.
Parmi les autres fonctionnalités proposées, on trouve également des améliorations de l’Intellisense, des APIs d’interopérabilités pour Option, des extensions async workflow pour WebClient.