Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
F# 6 ajoute plusieurs améliorations au langage F# et F# Interactive. Il est publié avec .NET 6.
Vous pouvez télécharger le dernier SDK .NET à partir de la page de téléchargements .NET.
Get started
F# 6 est disponible dans toutes les distributions .NET Core et les outils Visual Studio. Pour plus d’informations, consultez Prise en main de F#.
tâche {...}
F# 6 inclut la prise en charge native de la création de tâches .NET dans le code F# à l’aide d’expressions de tâche. Les expressions de tâche sont similaires aux expressions asynchrones, mais vous permettent de créer directement des tâches .NET.
Par exemple, considérez le code F# suivant pour créer une tâche compatible avec .NET :
let readFilesTask (path1, path2) =
async {
let! bytes1 = File.ReadAllBytesAsync(path1) |> Async.AwaitTask
let! bytes2 = File.ReadAllBytesAsync(path2) |> Async.AwaitTask
return Array.append bytes1 bytes2
} |> Async.StartAsTask
À l’aide de F# 6, ce code peut être réécrit comme suit.
let readFilesTask (path1, path2) =
task {
let! bytes1 = File.ReadAllBytesAsync(path1)
let! bytes2 = File.ReadAllBytesAsync(path2)
return Array.append bytes1 bytes2
}
La prise en charge des tâches était disponible pour F# 5 via les excellentes bibliothèques TaskBuilder.fs et Ply. Il doit être simple de migrer du code vers la prise en charge intégrée. Toutefois, il existe des différences : les espaces de noms et l’inférence de type diffèrent légèrement entre la prise en charge intégrée et ces bibliothèques, et certaines annotations de type supplémentaires peuvent être nécessaires. Si nécessaire, vous pouvez toujours utiliser ces bibliothèques de communauté avec F# 6 si vous les référencez explicitement et ouvrez les espaces de noms appropriés dans chaque fichier.
L’utilisation task {…} est très similaire à l’utilisation async {…}. L’utilisation task {…} présente plusieurs avantages sur async {…}:
- La surcharge de
task {...}est inférieure, ce qui peut améliorer les performances dans les parcours de code critique où le travail asynchrone s’exécute rapidement. - Le débogage pas à pas et les traces de pile pour
task {…}sont améliorés. - L’interopérabilité avec les packages .NET qui attendent ou produisent des tâches est plus facile.
Si vous êtes familiarisé avec async {…}, il existe quelques différences à connaître :
-
task {…}exécute immédiatement la tâche jusqu'au premier point d'attente. -
task {…}ne propage pas implicitement un jeton d’annulation. -
task {…}n’effectue pas de vérifications d’annulation implicites. -
task {…}ne prend pas en charge les appels de queue asynchrones. Cela signifie que l'utilisation récursive dereturn! ..peut entraîner des dépassements de pile en l’absence d’attente asynchrone intermédiaire.
En général, vous devriez envisager d’utiliser task {…} plutôt que async {…} dans le nouveau code si vous interagissez avec des bibliothèques .NET qui utilisent des tâches, et si vous ne dépendez pas des appels de code asynchrones ou de la propagation implicite du jeton d'annulation. Dans le code existant, vous ne devez passer à task {…} qu’après avoir examiné votre code pour vous assurer que vous ne vous appuyez pas sur les caractéristiques de async {…} mentionnées précédemment.
Cette fonctionnalité implémente F# RFC FS-1097.
Syntaxe d’indexation plus simple avec expr[idx]
F# 6 permet la syntaxe expr[idx] d’indexation et de découpage de collections.
Jusqu’à F# 5 et y compris, F# a utilisé expr.[idx] comme syntaxe d’indexation. L'autorisation d'utiliser expr[idx] est basée sur des retours répétés de ceux qui apprennent F# ou voient F# pour la première fois, qui considèrent que l'utilisation de l'indexation à notation pointée est perçue comme une divergence inutile par rapport aux pratiques standards du secteur.
Ce n’est pas un changement incompatible car, par défaut, aucun avertissement n’est émis sur l’utilisation de expr.[idx]. Toutefois, certains messages d’information qui suggèrent des clarifications de code sont émis. Vous pouvez également activer d’autres messages d’information. Par exemple, vous pouvez activer un avertissement d’information facultatif (/warnon:3366) pour commencer à signaler des utilisations de la expr.[idx] notation. Pour plus d’informations, consultez Notation de l’indexeur.
Dans le nouveau code, nous recommandons l’utilisation systématique de la syntaxe d’indexation avec expr[idx].
Cette fonctionnalité implémente F# RFC FS-1110.
Représentations des structures pour les motifs actifs partiels
F# 6 augmente la fonctionnalité « modèles actifs » avec des représentations de struct facultatives pour les modèles actifs partiels. Cela vous permet d’utiliser un attribut pour contraindre un modèle actif partiel à retourner une option de valeur :
[<return: Struct>]
let (|Int|_|) str =
match System.Int32.TryParse(str) with
| true, int -> ValueSome(int)
| _ -> ValueNone
L’utilisation de l’attribut est requise. Sur les sites d’utilisation, le code ne change pas. Le résultat net est que les allocations sont réduites.
Cette fonctionnalité implémente F# RFC FS-1039.
Opérations personnalisées surchargées dans les expressions de calcul
F# 6 vous permet d’utiliser CustomOperationAttribute sur les méthodes surchargées.
Considérez l’utilisation suivante d’un générateur contentd’expressions de calcul :
let mem = new System.IO.MemoryStream("Stream"B)
let content = ContentBuilder()
let ceResult =
content {
body "Name"
body (ArraySegment<_>("Email"B, 0, 5))
body "Password"B 2 4
body "BYTES"B
body mem
body "Description" "of" "content"
}
Ici, l’opération body personnalisée accepte un nombre variable d’arguments de différents types. Ceci est pris en charge par l’implémentation du générateur suivant, qui utilise la surcharge :
type Content = ArraySegment<byte> list
type ContentBuilder() =
member _.Run(c: Content) =
let crlf = "\r\n"B
[|for part in List.rev c do
yield! part.Array[part.Offset..(part.Count+part.Offset-1)]
yield! crlf |]
member _.Yield(_) = []
[<CustomOperation("body")>]
member _.Body(c: Content, segment: ArraySegment<byte>) =
segment::c
[<CustomOperation("body")>]
member _.Body(c: Content, bytes: byte[]) =
ArraySegment<byte>(bytes, 0, bytes.Length)::c
[<CustomOperation("body")>]
member _.Body(c: Content, bytes: byte[], offset, count) =
ArraySegment<byte>(bytes, offset, count)::c
[<CustomOperation("body")>]
member _.Body(c: Content, content: System.IO.Stream) =
let mem = new System.IO.MemoryStream()
content.CopyTo(mem)
let bytes = mem.ToArray()
ArraySegment<byte>(bytes, 0, bytes.Length)::c
[<CustomOperation("body")>]
member _.Body(c: Content, [<ParamArray>] contents: string[]) =
List.rev [for c in contents -> let b = Text.Encoding.ASCII.GetBytes c in ArraySegment<_>(b,0,b.Length)] @ c
Cette fonctionnalité implémente F# RFC FS-1056.
Modèles « as »
En F# 6, la partie droite d’un as motif peut maintenant elle-même être un motif. Cela est important lorsqu’un test de type a donné un type plus fort à une entrée. Considérons par exemple le code suivant :
type Pair = Pair of int * int
let analyzeObject (input: obj) =
match input with
| :? (int * int) as (x, y) -> printfn $"A tuple: {x}, {y}"
| :? Pair as Pair (x, y) -> printfn $"A DU: {x}, {y}"
| _ -> printfn "Nope"
let input = box (1, 2)
Dans chaque cas de modèle, l’objet d’entrée est testé de type. Le côté droit du as modèle est désormais autorisé à être un autre modèle, qui peut lui-même correspondre à l’objet au type plus fort.
Cette fonctionnalité implémente F# RFC FS-1105.
Révisions de la syntaxe de mise en retrait
F# 6 supprime un certain nombre d’incohérences et de limitations dans son utilisation de la syntaxe avec prise en compte de l'indentation. Voir RFC FS-1108. Cela résout 10 problèmes importants mis en évidence par les utilisateurs F# depuis F# 4.0.
Par exemple, dans F# 5, le code suivant a été autorisé :
let c = (
printfn "aaaa"
printfn "bbbb"
)
Toutefois, le code suivant n’a pas été autorisé (il a généré un avertissement) :
let c = [
1
2
]
En F# 6, les deux sont autorisés. Cela rend F# plus simple et plus facile à apprendre. Le contributeur de la communauté F# Hadrian Tang a ouvert la voie dans ce domaine, y compris des tests systématiques remarquables et très précieux de la fonctionnalité.
Cette fonctionnalité implémente F# RFC FS-1108.
Conversions implicites supplémentaires
Dans F# 6, nous avons activé la prise en charge des conversions implicites et dirigées par type, comme décrit dans RFC FS-1093.
Cette modification offre trois avantages :
- Moins de conversions explicites sont nécessaires
- Moins de conversions d’entiers explicites sont requises
- Prise en charge de première classe pour les conversions implicites de style .NET est ajoutée.
Cette fonctionnalité implémente F# RFC FS-1093.
Conversions implicites supplémentaires de upcast
F# 6 implémente des conversions implicites de type "upcast" supplémentaires. Par exemple, dans F# 5 et les versions antérieures, les upcasts étaient nécessaires pour l’expression de retour lors de l’implémentation d’une fonction où les expressions disposaient de sous-types différents sur différentes branches, même lorsqu’une annotation de type était présente. Considérez le code F# 5 suivant :
open System
open System.IO
let findInputSource () : TextReader =
if DateTime.Now.DayOfWeek = DayOfWeek.Monday then
// On Monday a TextReader
Console.In
else
// On other days a StreamReader
File.OpenText("path.txt") :> TextReader
Ici, les branches du conditionnel calculent respectivement TextReader et StreamReader, et la conversion ascendante a été ajoutée pour que les deux branches aient le type StreamReader. Dans la version F# 6, ces upcasts sont désormais ajoutés automatiquement. Cela signifie que le code est plus simple :
let findInputSource () : TextReader =
if DateTime.Now.DayOfWeek = DayOfWeek.Monday then
// On Monday a TextReader
Console.In
else
// On other days a StreamReader
File.OpenText("path.txt")
Vous pouvez éventuellement activer l’avertissement /warnon:3388 pour afficher un avertissement à chaque point où une conversion ascendante implicite supplémentaire est utilisée, comme décrit dans Avertissements facultatifs pour les conversions implicites.
Conversions d’entiers implicites
Dans F# 6, les entiers 32 bits sont élargis à des entiers 64 bits lorsque les deux types sont connus. Par exemple, considérez une forme d’API classique :
type Tensor(…) =
static member Create(sizes: seq<int64>) = Tensor(…)
Dans F# 5, les littéraux entiers pour int64 doivent être utilisés :
Tensor.Create([100L; 10L; 10L])
ou
Tensor.Create([int64 100; int64 10; int64 10])
En F# 6, l’élargissement se produit automatiquement pour int32int64, int32 vers nativeintet int32 vers double, lorsque le type source et de destination sont connus pendant l’inférence de type. Ainsi, dans des cas tels que les exemples précédents, les littéraux int32 peuvent être utilisés :
Tensor.Create([100; 10; 10])
Malgré ce changement, F# continue d’utiliser l’élargissement explicite des types numériques dans la plupart des cas. Par exemple, l’élargissement implicite ne s’applique pas à d’autres types numériques, tels que int8 ou int16, depuis float32 ou vers float64, ou lorsque le type source ou de destination est inconnu. Vous pouvez également activer l’avertissement /warnon:3389 pour afficher un avertissement à chaque point que l’élargissement numérique implicite est utilisé, comme décrit dans Avertissements facultatifs pour les conversions implicites.
Prise en charge optimale pour les conversions implicites de style .NET
Dans F# 6, les conversions « op_Implicit » .NET sont appliquées automatiquement dans le code F# lors de l’appel de méthodes. Par exemple, dans F# 5, il était nécessaire d’utiliser XName.op_Implicit lors de l’utilisation des API .NET pour XML :
open System.Xml.Linq
let purchaseOrder = XElement.Load("PurchaseOrder.xml")
let partNos = purchaseOrder.Descendants(XName.op_Implicit "Item")
Dans F# 6, op_Implicit les conversions sont appliquées automatiquement pour les expressions d’argument lorsque les types sont disponibles pour l’expression source et le type cible :
open System.Xml.Linq
let purchaseOrder = XElement.Load("PurchaseOrder.xml")
let partNos = purchaseOrder.Descendants("Item")
Vous pouvez éventuellement activer l'avertissement /warnon:3395 pour afficher un avertissement à chaque fois que l'élargissement des conversions est utilisé dans les arguments de méthode, comme décrit dans Avertissements facultatifs pour les conversions implicites.
Note
Dans la première version de F# 6, ce numéro d’avertissement était /warnon:3390. En raison d’un conflit, le numéro d’avertissement a été mis à jour ultérieurement vers /warnon:3395.
Avertissements facultatifs pour les conversions implicites
Les conversions dirigées par type et implicites peuvent interagir mal avec l’inférence de type et conduire au code plus difficile à comprendre. Pour cette raison, certaines atténuations existent pour vous assurer que cette fonctionnalité n’est pas abusée dans le code F#. Tout d’abord, le type source et de destination doit être fortement connu, sans ambiguïté ni inférence de type supplémentaire résultant. Deuxièmement, les avertissements optionnels peuvent être activés pour signaler toute utilisation des conversions implicites, avec un avertissement activé par défaut :
-
/warnon:3388(upcast implicite supplémentaire) -
/warnon:3389(élargissement numérique implicite) -
/warnon:3391(op_Implicit sur les arguments hors méthode, activé par défaut) -
/warnon:3395(op_Implicit pour les arguments de méthode)
Si votre équipe souhaite interdire toutes les utilisations de conversions implicites, vous pouvez également spécifier /warnaserror:3388, /warnaserror:3389, /warnaserror:3391et /warnaserror:3395.
Mise en forme des nombres binaires
F# 6 ajoute le %B modèle aux spécificateurs de format disponibles pour les formats de nombre binaire. Considérez le code F# suivant :
printf "%o" 123
printf "%B" 123
Ce code imprime la sortie suivante :
173
1111011
Cette fonctionnalité implémente F# RFC FS-1100.
Ignorer les liaisons d’utilisation
F# 6 permet _ d’être utilisé dans une use liaison, par exemple :
let doSomething () =
use _ = System.IO.File.OpenText("input.txt")
printfn "reading the file"
Cette fonctionnalité implémente F# RFC FS-1102.
InlineIfLambda
Le compilateur F# inclut un optimiseur qui effectue l’incorporation de code. Dans F# 6, nous avons ajouté une nouvelle fonctionnalité déclarative qui permet au code d’indiquer éventuellement que, si un argument est déterminé comme une fonction lambda, cet argument doit toujours être inclus dans les sites d’appel.
Par exemple, considérez la fonction suivante iterateTwice pour parcourir un tableau :
let inline iterateTwice ([<InlineIfLambda>] action) (array: 'T[]) =
for j = 0 to array.Length-1 do
action array[j]
for j = 0 to array.Length-1 do
action array[j]
Si le site d’appel est :
let arr = [| 1.. 100 |]
let mutable sum = 0
arr |> iterateTwice (fun x ->
sum <- sum + x)
Ensuite, après l’incorporation et d’autres optimisations, le code devient :
let arr = [| 1.. 100 |]
let mutable sum = 0
for j = 0 to arr.Length-1 do
sum <- sum + arr[j]
for j = 0 to arr.Length-1 do
sum <- sum + arr[j]
Contrairement aux versions précédentes de F#, cette optimisation est appliquée indépendamment de la taille de l’expression lambda impliquée. Cette fonctionnalité peut également être utilisée pour implémenter un déroulement de boucle et des transformations similaires de manière plus fiable.
Un avertissement d’opt-in (/warnon:3517désactivé par défaut) peut être activé pour indiquer des emplacements dans votre code où InlineIfLambda les arguments ne sont pas liés aux expressions lambda sur les sites d’appel. Dans des situations normales, cet avertissement ne doit pas être activé. Toutefois, dans certains types de programmation hautes performances, il peut être utile de s’assurer que tout le code est inline et aplatit.
Cette fonctionnalité implémente F# RFC FS-1098.
Code pouvant être repris
La task {…} prise en charge de F# 6 est construite sur une fondation appelée code résumableRFC FS-1087. Le code pouvant être repris est une fonctionnalité technique qui peut être utilisée pour créer de nombreux types de machines asynchrones hautes performances et produisant des états.
Fonctions de collection supplémentaires
FSharp.Core 6.0.0 ajoute cinq nouvelles opérations aux fonctions de collection principales. Ces fonctions sont les suivantes :
- List/Array/Seq.insertAt
- List/Array/Seq.removeAt
- List/Array/Seq.updateAt
- List/Array/Seq.insertManyAt
- List/Array/Seq.removeManyAt
Ces fonctions effectuent toutes des opérations de copie et de mise à jour sur le type ou la séquence de collection correspondant. Ce type d’opération est une forme de « mise à jour fonctionnelle ». Pour obtenir des exemples d’utilisation de ces fonctions, consultez la documentation correspondante, par exemple List.insertAt.
Par exemple, considérez le modèle, le message et la logique de mise à jour pour une application simple « Todo List » écrite dans le style Elmish. Ici, l’utilisateur interagit avec l’application, génère des messages et la update fonction traite ces messages, produisant un nouveau modèle :
type Model =
{ ToDo: string list }
type Message =
| InsertToDo of index: int * what: string
| RemoveToDo of index: int
| LoadedToDos of index: int * what: string list
let update (model: Model) (message: Message) =
match message with
| InsertToDo (index, what) ->
{ model with ToDo = model.ToDo |> List.insertAt index what }
| RemoveToDo index ->
{ model with ToDo = model.ToDo |> List.removeAt index }
| LoadedToDos (index, what) ->
{ model with ToDo = model.ToDo |> List.insertManyAt index what }
Avec ces nouvelles fonctions, la logique est claire et simple et s’appuie uniquement sur des données immuables.
Cette fonctionnalité implémente F# RFC FS-1113.
La carte a des clés et des valeurs
Dans FSharp.Core 6.0.0, le Map type prend désormais en charge les propriétés Clés et Valeurs . Ces propriétés ne copient pas la collection sous-jacente.
Cette fonctionnalité est documentée dans F# RFC FS-1113.
Fonctions intrinsèques supplémentaires pour NativePtr
FSharp.Core 6.0.0 ajoute de nouvelles intrinsèques au module NativePtr :
NativePtr.nullPtrNativePtr.isNullPtrNativePtr.initBlockNativePtr.clearNativePtr.copyNativePtr.copyBlockNativePtr.ofILSigPtrNativePtr.toILSigPtr
Comme avec d’autres fonctions dans NativePtr, ces fonctions sont inline et leur utilisation émet des avertissements, sauf s’il /nowarn:9 est utilisé. L’utilisation de ces fonctions est limitée aux types non managés.
Cette fonctionnalité est documentée dans F# RFC FS-1109.
Types numériques supplémentaires avec annotations d’unité
Dans F# 6, les types ou alias d’abréviation de type suivants prennent désormais en charge les annotations unitaires de mesure. Les nouveaux ajouts sont affichés en gras :
| Alias F# | Type CLR |
|---|---|
float32/single |
System.Single |
float/double |
System.Double |
decimal |
System.Decimal |
sbyte/int8 |
System.SByte |
int16 |
System.Int16 |
int/int32 |
System.Int32 |
int64 |
System.Int64 |
byte/uint8 |
System.Byte |
uint16 |
System.UInt16 |
uint/uint32 |
System.UInt32 |
uint64 |
System.UIn64 |
nativeint |
System.IntPtr |
unativeint |
System.UIntPtr |
Par exemple, vous pouvez annoter un entier non signé comme suit :
[<Measure>]
type days
let better_age = 3u<days>
Cette fonctionnalité est documentée dans F# RFC FS-1091.
Avertissements d’information pour les opérateurs symboliques rarement utilisés
F# 6 ajoute des conseils souples qui dé-normalisent l’utilisation de :=, !, incret decr en F# 6 et au-delà. L’utilisation de ces opérateurs et fonctions produit des messages d’information qui vous demandent de remplacer votre code par une utilisation explicite de la Value propriété.
Dans la programmation F#, les cellules de référence peuvent être utilisées pour les registres mutables alloués sur le tas. Bien qu’ils soient parfois utiles, ils sont rarement nécessaires dans le codage F# moderne, car let mutable ils peuvent être utilisés à la place. La bibliothèque principale F# comprend deux opérateurs := et ! deux fonctions incr et decr spécifiquement liées aux appels de référence. La présence de ces opérateurs rend les cellules de référence plus centrales à la programmation F# qu’elles ne doivent être, ce qui nécessite que tous les programmeurs F# sachent ces opérateurs. En outre, l'opérateur ! peut être facilement confondu avec l'opération not en C# et dans d'autres langages, une source potentiellement subtile de bogues lors de la traduction de code.
La raison de ce changement est de réduire le nombre d’opérateurs que le programmeur F# doit connaître, et donc simplifier F# pour les débutants.
Par exemple, considérez le code F# 5 suivant :
let r = ref 0
let doSomething() =
printfn "doing something"
r := !r + 1
Tout d’abord, les cellules de référence sont rarement nécessaires dans le codage F# moderne, car elles let mutable peuvent normalement être utilisées à la place :
let mutable r = 0
let doSomething() =
printfn "doing something"
r <- r + 1
Si vous utilisez des cellules de référence, F# 6 émet un avertissement informatif vous demandant de modifier la dernière ligne à r.Value <- r.Value + 1, et vous fournit des conseils supplémentaires sur l’utilisation appropriée des cellules de référence.
let r = ref 0
let doSomething() =
printfn "doing something"
r.Value <- r.Value + 1
Ces messages ne sont pas des avertissements ; il s’agit de « messages d’information » affichés dans l’IDE et la sortie du compilateur. F# reste rétrocompatible.
Cette fonctionnalité implémente F# RFC FS-1111.
Outils F# : .NET 6 la valeur par défaut pour l’écriture de scripts dans Visual Studio
Si vous ouvrez ou exécutez un script F# (.fsx) dans Visual Studio, par défaut, le script sera analysé et exécuté à l’aide de .NET 6 avec une exécution 64 bits. Cette fonctionnalité était en préversion dans les versions ultérieures de Visual Studio 2019 et est désormais activée par défaut.
Pour activer le script .NET Framework, sélectionnez Outils>Options>Outils F#>F# Interactive. Définissez Utiliser le script .NET Core sur false, puis redémarrez la fenêtre interactive F#. Ce paramètre affecte à la fois l’édition de script et l’exécution de script. Pour activer l’exécution 32 bits pour le script .NET Framework, définissez également F# Interactive 64 bits sur false. Il n’existe aucune option 32 bits pour le script .NET Core.
Outils F# : épingler la version du Kit de développement logiciel (SDK) de vos scripts F#
Si vous exécutez un script à l’aide dotnet fsi d’un répertoire contenant un fichier global.json avec un paramètre sdk .NET, la version répertoriée du Kit de développement logiciel (SDK) .NET sera utilisée pour exécuter et modifier le script. Cette fonctionnalité a été disponible dans les versions ultérieures de F# 5.
Par exemple, supposons qu’il existe un script dans un répertoire avec le fichier global.json suivant spécifiant une stratégie de version du Kit de développement logiciel (SDK) .NET :
{
"sdk": {
"version": "5.0.200",
"rollForward": "minor"
}
}
Si vous exécutez maintenant le script à l’aide dotnet fside ce répertoire, la version du Kit de développement logiciel (SDK) sera respectée. Il s’agit d’une fonctionnalité puissante qui vous permet de « verrouiller » le Kit de développement logiciel (SDK) utilisé pour compiler, analyser et exécuter vos scripts.
Si vous ouvrez et modifiez votre script dans Visual Studio et d’autres IDE, les outils respectent ce paramètre lors de l’analyse et de la vérification de votre script. Si le Kit de développement logiciel (SDK) est introuvable, vous devez l’installer sur votre ordinateur de développement.
Sur Linux et d’autres systèmes Unix, vous pouvez combiner cela avec un shebang pour spécifier également une version de langage pour l’exécution directe du script. Un shebang simple pour script.fsx est :
#!/usr/bin/env -S dotnet fsi
printfn "Hello, world"
À présent, le script peut être exécuté directement avec script.fsx. Vous pouvez combiner ceci avec une version de langue spécifique et non par défaut comme suit :
#!/usr/bin/env -S dotnet fsi --langversion:5.0
Note
Ce paramètre est ignoré par les outils d’édition, qui analysent le script en supposant la dernière version du langage.
Suppression des fonctionnalités héritées
Depuis F# 2.0, certaines fonctionnalités héritées déconseillées ont longtemps donné des avertissements. L’utilisation de ces fonctionnalités dans F# 6 donne des erreurs, sauf si vous utilisez /langversion:5.0explicitement . Les fonctionnalités qui fournissent des erreurs sont les suivantes :
- Plusieurs paramètres génériques utilisant un nom de type postfix, par exemple
(int, int) Dictionary. Cela devient une erreur en F# 6. La syntaxeDictionary<int,int>standard doit être utilisée à la place. -
#indent "off". Cela devient une erreur. -
x.(expr). Cela devient une erreur. -
module M = struct … end. Cela devient une erreur. - Utilisation des entrées
*.mlet*.mli. Cela devient une erreur. - Utilisation de
(*IF-CAML*)ou(*IF-OCAML*). Cela devient une erreur. - Utilisation de
land,lor,lxor,lsl,lsrouasren tant qu’opérateurs infixes. Ces mots clés sont infixés en F# car ils étaient des mots clés infix dans OCaml et ne sont pas définis dans FSharp.Core. L’utilisation de ces mots clés émet désormais un avertissement.
Cela implémente F# RFC FS-1114.