Nieuw in F# 6

F# 6 voegt verschillende verbeteringen toe aan de F#-taal en F# Interactive. Het wordt uitgebracht met .NET 6.

U kunt de nieuwste .NET SDK downloaden via de .NET-downloadpagina.

Aan de slag

F# 6 is beschikbaar in alle .NET Core-distributies en Visual Studio-hulpprogramma's. Zie Aan de slag met F# voor meer informatie.

taak {...}

F# 6 bevat systeemeigen ondersteuning voor het ontwerpen van .NET-taken in F#-code. Denk bijvoorbeeld aan de volgende F#-code om een . Net-compatibele taak:

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

Met F# 6 kan deze code als volgt worden herschreven.

let readFilesTask (path1, path2) =
   task {
        let! bytes1 = File.ReadAllBytesAsync(path1)
        let! bytes2 = File.ReadAllBytesAsync(path2)
        return Array.append bytes1 bytes2
   }

Taakondersteuning was beschikbaar voor F# 5 via de uitstekende TaskBuilder.fs- en Ply-bibliotheken. Het moet eenvoudig zijn om code te migreren naar de ingebouwde ondersteuning. Er zijn echter enkele verschillen: naamruimten en typedeductie verschillen enigszins tussen de ingebouwde ondersteuning en deze bibliotheken, en sommige aanvullende typeaantekeningen zijn mogelijk nodig. Indien nodig kunt u deze communitybibliotheken nog steeds gebruiken met F# 6 als u er expliciet naar verwijst en de juiste naamruimten in elk bestand opent.

Het gebruik task {…} is vergelijkbaar met het gebruik async {…}. Het gebruik task {…} heeft verschillende voordelen ten opzichte van async {…}:

  • De overhead van task {...} is lager, waardoor de prestaties in dynamische-codepaden mogelijk worden verbeterd, waarbij het asynchrone werk snel wordt uitgevoerd.
  • Foutopsporing voor stap- en stacktraceringen task {…} is beter.
  • Samenwerken met .NET-pakketten die taken verwachten of produceren, is eenvoudiger.

Als u bekend bent, async {…}zijn er enkele verschillen waarmee u rekening moet houden:

  • task {…} voert de taak onmiddellijk uit naar het eerste wachtpunt.
  • task {…} geeft geen annuleringstoken impliciet door.
  • task {…} voert geen impliciete annuleringscontroles uit.
  • task {…} biedt geen ondersteuning voor asynchrone tailcalls. Dit betekent dat het gebruik van return! .. recursief kan leiden tot stack-overloop als er geen tussenliggende asynchrone wachttijden zijn.

Over het algemeen moet u overwegen om nieuwe code te async {…} gebruiken task {…} als u werkt met .NET-bibliotheken die gebruikmaken van taken en als u niet vertrouwt op asynchrone code tailcalls of impliciete doorgifte van annuleringstokens. In bestaande code moet u alleen overschakelen naar task {…} zodra u de code hebt gecontroleerd om ervoor te zorgen dat u niet vertrouwt op de eerder genoemde kenmerken van async {…}.

Met deze functie wordt F# RFC FS-1097 geïmplementeerd.

Eenvoudigere indexeringsyntaxis met expr[idx]

Met F# 6 kunnen verzamelingen met indexering en segmentering worden geïndexeerde expr[idx] en geliceerde verzamelingen.

Tot en met F# 5 heeft F# gebruikt expr.[idx] als indexeringsyntaxis. Het gebruik van expr[idx] is gebaseerd op herhaalde feedback van degenen die F# leren of F# zien voor de eerste keer dat het gebruik van dot-notatie-indexering voorkomt als een onnodige afwijking van de standaardindustriepraktijk.

Dit is geen wijziging die fouten veroorzaakt, omdat er standaard geen waarschuwingen worden verzonden bij het gebruik van expr.[idx]. Sommige informatieve berichten die voorstellen dat code-verduidelijkingen worden verzonden, worden echter verzonden. U kunt desgewenst ook verdere informatieve berichten activeren. U kunt bijvoorbeeld een optionele informatieve waarschuwing (/warnon:3566) activeren om te beginnen met het rapporteren van gebruik van de expr.[idx] notatie. Zie Notatie voor indexeerfunctie voor meer informatie.

In nieuwe code raden we het systematische gebruik aan van expr[idx] als de indexeringsyntaxis.

Met deze functie wordt F# RFC FS-1110 geïmplementeerd.

Struct-representaties voor gedeeltelijke actieve patronen

F# 6 vergroot de functie 'actieve patronen' met optionele struct-weergaven voor gedeeltelijke actieve patronen. Hiermee kunt u een kenmerk gebruiken om een gedeeltelijk actief patroon te beperken om een waardeoptie te retourneren:

[<return: Struct>]
let (|Int|_|) str =
   match System.Int32.TryParse(str) with
   | true, int -> ValueSome(int)
   | _ -> ValueNone

Het gebruik van het kenmerk is vereist. Op gebruikssites wordt de code niet gewijzigd. Het nettoresultaat is dat toewijzingen worden verminderd.

Met deze functie wordt F# RFC FS-1039 geïmplementeerd.

Overbelaste aangepaste bewerkingen in berekeningsexpressies

Met F# 6 kunt u CustomOperationAttribute gebruiken op de overbelaste methoden.

Overweeg het volgende gebruik van een opbouwfunctie contentvoor rekenexpressies:

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"
    }

Hier heeft de body aangepaste bewerking een verschillend aantal argumenten van verschillende typen. Dit wordt ondersteund door de implementatie van de volgende opbouwfunctie, die gebruikmaakt van overbelasting:

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

Met deze functie wordt F# RFC FS-1056 geïmplementeerd.

'as'-patronen

In F# 6 kan de rechterkant van een as patroon nu zelf een patroon zijn. Dit is belangrijk wanneer een typetest een sterker type aan een invoer heeft gegeven. Denk bijvoorbeeld aan de volgende code:

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)

In elk patroon wordt het invoerobject getypt. De rechterkant van het as patroon is nu toegestaan om een ander patroon te zijn, dat zichzelf kan aanpassen aan het object op het sterkere type.

Met deze functie wordt F# RFC FS-1105 geïmplementeerd.

Revisies van de inspringingssyntaxis

F# 6 verwijdert een aantal inconsistenties en beperkingen in het gebruik van inspringingsbewuste syntaxis. Zie RFC FS-1108. Hiermee worden 10 belangrijke problemen opgelost die zijn gemarkeerd door F#-gebruikers sinds F# 4.0.

In F# 5 is bijvoorbeeld de volgende code toegestaan:

let c = (
    printfn "aaaa"
    printfn "bbbb"
)

De volgende code is echter niet toegestaan (er is een waarschuwing gegenereerd):

let c = [
    1
    2
]

In F# 6 zijn beide toegestaan. Hierdoor is F# eenvoudiger en gemakkelijker te leren. De inzender van de F#-community Hadrian Tang heeft hiertoe geleid, waaronder opmerkelijk en zeer waardevol systematisch testen van de functie.

Met deze functie wordt F# RFC FS-1108 geïmplementeerd.

Aanvullende impliciete conversies

In F# 6 hebben we ondersteuning geactiveerd voor aanvullende 'impliciete' en 'typegestuurde' conversies, zoals beschreven in RFC FS-1093.

Deze wijziging biedt drie voordelen:

  1. Er zijn minder expliciete upcasts vereist
  2. Er zijn minder expliciete gehele getallen vereist
  3. Eersteklas ondersteuning voor . Impliciete conversies in NET-stijl worden toegevoegd

Met deze functie wordt F# RFC FS-1093 geïmplementeerd.

Aanvullende impliciete upcast-conversies

Met F# 6 worden aanvullende impliciete upcast-conversies geïmplementeerd. In F# 5 en eerdere versies waren bijvoorbeeld upcasts nodig voor de retourexpressie bij het implementeren van een functie waarbij de expressies verschillende subtypen op verschillende vertakkingen hadden, zelfs wanneer een typeaantekening aanwezig was. Houd rekening met de volgende F# 5-code:

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

Hier zijn de vertakkingen van de voorwaardelijke berekening a TextReader en StreamReader respectievelijk toegevoegd, en de upcast is toegevoegd om beide vertakkingen te laten beschikken over het type StreamReader. In F# 6 worden deze upcasts nu automatisch toegevoegd. Dit betekent dat de code eenvoudiger is:

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")

U kunt eventueel de waarschuwing /warnon:3388 inschakelen om een waarschuwing weer te geven op elk moment dat een aanvullende impliciete upcast wordt gebruikt, zoals beschreven in optionele waarschuwingen voor impliciete conversies.

Impliciete conversies van gehele getallen

In F# 6 worden 32-bits gehele getallen uitgebreid tot 64-bits gehele getallen wanneer beide typen bekend zijn. Denk bijvoorbeeld aan een typische API-shape:

type Tensor(…) =
    static member Create(sizes: seq<int64>) = Tensor(…)

In F# 5 moeten letterlijke gehele getallen voor int64 worden gebruikt:

Tensor.Create([100L; 10L; 10L])

or

Tensor.Create([int64 100; int64 10; int64 10])

In F# 6 treedt de widening automatisch op voor int32 , int64int32 tot nativeinten int32 met double, wanneer zowel het bron- als het doeltype bekend zijn tijdens typedeductie. In gevallen zoals de vorige voorbeelden int32 kunnen letterlijke waarden dus worden gebruikt:

Tensor.Create([100; 10; 10])

Ondanks deze wijziging blijft F# in de meeste gevallen expliciete verbreiding van numerieke typen gebruiken. Impliciete widening is bijvoorbeeld niet van toepassing op andere numerieke typen, zoals int8 of , of int16van float32 naar float64, of wanneer bron- of doeltype onbekend is. U kunt de waarschuwing /warnon:3389 desgewenst ook inschakelen om een waarschuwing weer te geven op elk punt dat impliciete numerieke widening wordt gebruikt, zoals beschreven in optionele waarschuwingen voor impliciete conversies.

Eersteklas ondersteuning voor . Impliciete conversies in NET-stijl

In F# 6 worden .NET-conversies 'op_Implicit' automatisch toegepast in F#-code bij het aanroepen van methoden. In F# 5 was het bijvoorbeeld nodig om te gebruiken XName.op_Implicit bij het werken met .NET-API's voor XML:

open System.Xml.Linq
let purchaseOrder = XElement.Load("PurchaseOrder.xml")
let partNos = purchaseOrder.Descendants(XName.op_Implicit "Item")

In F# 6 op_Implicit worden conversies automatisch toegepast voor argumentexpressies wanneer typen beschikbaar zijn voor bronexpressie en doeltype:

open System.Xml.Linq
let purchaseOrder = XElement.Load("PurchaseOrder.xml")
let partNos = purchaseOrder.Descendants("Item")

U kunt eventueel de waarschuwing /warnon:3395 inschakelen om een waarschuwing weer te geven bij elke op_Implicit puntconversie die wordt gebruikt bij methodeargumenten, zoals beschreven in optionele waarschuwingen voor impliciete conversies.

Notitie

In de eerste versie van F# 6 was /warnon:3390dit waarschuwingsnummer. Vanwege een conflict is het waarschuwingsnummer later bijgewerkt naar /warnon:3395.

Optionele waarschuwingen voor impliciete conversies

Typegestuurde en impliciete conversies kunnen slecht communiceren met typedeductie en leiden tot code die moeilijker te begrijpen is. Daarom bestaan er enkele oplossingen om ervoor te zorgen dat deze functie niet wordt misbruikt in F#-code. Ten eerste moeten zowel het bron- als het doeltype sterk bekend zijn, zonder dubbelzinnigheid of aanvullende typedeductie die ontstaat. Ten tweede kunnen opt-in-waarschuwingen worden geactiveerd om elk gebruik van impliciete conversies te rapporteren, waarbij standaard één waarschuwing is ingeschakeld:

  • /warnon:3388 (aanvullende impliciete upcast)
  • /warnon:3389 (impliciete numerieke widening)
  • /warnon:3391 (op_Implicit bij niet-methodeargumenten, standaard ingeschakeld)
  • /warnon:3395 (op_Implicit bij methodeargumenten)

Als uw team alle gebruik van impliciete conversies wil verbieden, kunt u ook opgeven /warnaserror:3388, /warnaserror:3389, /warnaserror:3391en /warnaserror:3395.

Opmaak voor binaire getallen

Met F# 6 wordt het %B patroon toegevoegd aan de beschikbare notatieaanduidingen voor binaire getalnotaties. Houd rekening met de volgende F#-code:

printf "%o" 123
printf "%B" 123

Met deze code wordt de volgende uitvoer afgedrukt:

173
1111011

Met deze functie wordt F# RFC FS-1100 geïmplementeerd.

Verwijderingen voor gebruiksbindingen

Met F# 6 kan _ bijvoorbeeld in een use binding worden gebruikt:

let doSomething () =
    use _ = System.IO.File.OpenText("input.txt")
    printfn "reading the file"

Met deze functie wordt F# RFC FS-1102 geïmplementeerd.

InlineIfLambda

De F#-compiler bevat een optimalisatieprogramma waarmee code wordt geïnlind. In F# 6 hebben we een nieuwe declaratieve functie toegevoegd waarmee code optioneel kan worden aangegeven dat, als een argument een lambda-functie is, dat argument altijd inline moet zijn op oproepsites.

Denk bijvoorbeeld aan de volgende iterateTwice functie om een matrix te doorlopen:

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]

Als de oproepsite het volgende is:

let arr = [| 1.. 100 |]
let mutable sum = 0
arr  |> iterateTwice (fun x ->
    sum <- sum + x)

Daarna wordt de code na het inlijnen en andere optimalisaties:

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]

In tegenstelling tot eerdere versies van F# wordt deze optimalisatie toegepast, ongeacht de grootte van de lambda-expressie. Deze functie kan ook worden gebruikt om lus uitschrijven en vergelijkbare transformaties betrouwbaarder te implementeren.

Een opt-in-waarschuwing (/warnon:3517standaard uitgeschakeld) kan worden ingeschakeld om plaatsen in uw code aan te geven waarbij InlineIfLambda argumenten niet zijn gebonden aan lambda-expressies op oproepsites. In normale situaties mag deze waarschuwing niet worden ingeschakeld. In bepaalde soorten programmeren met hoge prestaties kan het echter handig zijn om ervoor te zorgen dat alle code inline en afgevlakt is.

Met deze functie wordt F# RFC FS-1098 geïmplementeerd.

Hervatbare code

De task {…} ondersteuning van F# 6 is gebouwd op een basis genaamd hervatbare codeRFC FS-1087. Hervatbare code is een technische functie die kan worden gebruikt voor het bouwen van veel soorten asynchrone asynchrone high performance en het opleveren van statusmachines.

Aanvullende verzamelingsfuncties

FSharp.Core 6.0.0 voegt vijf nieuwe bewerkingen toe aan de kernverzamelingsfuncties. Deze functies zijn:

  • List/Array/Seq.insertAt
  • List/Array/Seq.removeAt
  • List/Array/Seq.updateAt
  • List/Array/Seq.insertManyAt
  • List/Array/Seq.removeManyAt

Deze functies voeren allemaal kopieer- en updatebewerkingen uit op het bijbehorende verzamelingstype of de bijbehorende reeks. Dit type bewerking is een vorm van een 'functionele update'. Zie de bijbehorende documentatie, bijvoorbeeld List.insertAt, voor voorbeelden van het gebruik van deze functies.

Bekijk bijvoorbeeld het model, het bericht en de updatelogica voor een eenvoudige 'Takenlijst'-toepassing die is geschreven in de Elmish-stijl. Hier communiceert de gebruiker met de toepassing, genereert berichten en verwerkt de update functie deze berichten, waardoor een nieuw model wordt geproduceerd:

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 }

Met deze nieuwe functies is de logica duidelijk en eenvoudig en is alleen afhankelijk van onveranderbare gegevens.

Met deze functie wordt F# RFC FS-1113 geïmplementeerd.

Kaart bevat sleutels en waarden

In FSharp.Core 6.0.0 ondersteunt het Map type nu de eigenschappen Sleutels en Waarden . Met deze eigenschappen wordt de onderliggende verzameling niet gekopieerd.

Deze functie wordt beschreven in F# RFC FS-1113.

Aanvullende intrinsiek voor NativePtr

FSharp.Core 6.0.0 voegt nieuwe intrinsieken toe aan de NativePtr-module :

  • NativePtr.nullPtr
  • NativePtr.isNullPtr
  • NativePtr.initBlock
  • NativePtr.clear
  • NativePtr.copy
  • NativePtr.copyBlock
  • NativePtr.ofILSigPtr
  • NativePtr.toILSigPtr

Net als bij andere functies worden NativePtrdeze functies inline geplaatst en worden waarschuwingen verzonden, tenzij /nowarn:9 ze worden gebruikt. Het gebruik van deze functies is beperkt tot niet-beheerde typen.

Deze functie wordt beschreven in F# RFC FS-1109.

Aanvullende numerieke typen met eenheidsaantekeningen

In F# 6 bieden de volgende typen of afkortingsaliassen nu ondersteuning voor aantekeningen per maateenheid. De nieuwe toevoegingen worden vet weergegeven:

F#-alias CLR-type
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

U kunt bijvoorbeeld als volgt aantekeningen maken op een niet-ondertekend geheel getal:

[<Measure>]
type days

let better_age = 3u<days>

Deze functie wordt beschreven in F# RFC FS-1091.

Informatieve waarschuwingen voor zelden gebruikte symbolische operatoren

F# 6 voegt zachte richtlijnen toe waarmee het gebruik van :=, !en incrdecr in F# 6 en hoger ongedaan wordt gemaakt. Als u deze operators en functies gebruikt, worden informatieve berichten gegenereerd die u vragen uw code te vervangen door expliciet gebruik van de Value eigenschap.

In F#-programmering kunnen verwijzingscellen worden gebruikt voor door heap toegewezen muteerbare registers. Hoewel ze af en toe nuttig zijn, zijn ze zelden nodig in moderne F#-codering, omdat let mutable ze in plaats daarvan kunnen worden gebruikt. De F#-kernbibliotheek bevat twee operators := en ! twee functies incr en decr specifiek gerelateerd aan verwijzingsoproepen. De aanwezigheid van deze operators maakt verwijzingscellen centraler voor F#-programmering dan nodig is, waardoor alle F#-programmeurs deze operators moeten kennen. Verder kan de ! operator gemakkelijk worden verward met de not bewerking in C# en andere talen, een mogelijk subtiele bron van bugs bij het vertalen van code.

De reden voor deze wijziging is het verminderen van het aantal operators dat de F#-programmeur moet weten en dus F# voor beginners vereenvoudigen.

Denk bijvoorbeeld aan de volgende F# 5-code:

let r = ref 0

let doSomething() =
    printfn "doing something"
    r := !r + 1

In de eerste plaats zijn verwijzingscellen zelden nodig in moderne F#-codering, zoals let mutable normaal gesproken kan worden gebruikt:

let mutable r = 0

let doSomething() =
    printfn "doing something"
    r <- r + 1

Als u verwijzingscellen gebruikt, wordt in F# 6 een informatieve waarschuwing weergegeven waarin u wordt gevraagd om de laatste regel te r.Value <- r.Value + 1wijzigen in en wordt u gekoppeld aan verdere richtlijnen voor het juiste gebruik van verwijzingscellen.

let r = ref 0

let doSomething() =
    printfn "doing something"
    r.Value <- r.Value + 1

Deze berichten zijn geen waarschuwingen; ze zijn 'informatieve berichten' die worden weergegeven in de IDE- en compileruitvoer. F# blijft compatibel met eerdere versies.

Met deze functie wordt F# RFC FS-1111 geïmplementeerd.

F#-hulpprogramma's: .NET 6 de standaardinstelling voor scripting in Visual Studio

Als u een F#-script (.fsx) opent of uitvoert in Visual Studio, wordt het script standaard geanalyseerd en uitgevoerd met .NET 6 met 64-bits uitvoering. Deze functionaliteit was in preview in de latere versies van Visual Studio 2019 en is nu standaard ingeschakeld.

Als u .NET Framework-scripts wilt inschakelen, selecteert u Tools>Options>F# Tools>F# Interactive. Stel Use .NET Core Scripting in opfalse en start het venster F# Interactive opnieuw op. Deze instelling is van invloed op zowel het bewerken van scripts als het uitvoeren van scripts. Als u 32-bits uitvoering wilt inschakelen voor .NET Framework-scripts, stelt u ook 64-bits F# Interactive in op false. Er is geen 32-bits optie voor .NET Core-scripts.

F#-hulpprogramma's: De SDK-versie van uw F#-scripts vastmaken

Als u een script uitvoert in dotnet fsi een map met een global.json-bestand met een .NET SDK-instelling, wordt de vermelde versie van de .NET SDK gebruikt om het script uit te voeren en te bewerken. Deze functie is beschikbaar in de latere versies van F# 5.

Stel dat er een script in een map staat met het volgende global.json bestand dat een .NET SDK-versiebeleid opgeeft:

{
  "sdk": {
    "version": "5.0.200",
    "rollForward": "minor"
  }
}

Als u het script nu uitvoert met behulp dotnet fsivan deze map, wordt de SDK-versie gerespecteerd. Dit is een krachtige functie waarmee u de SDK kunt vergrendelen die wordt gebruikt voor het compileren, analyseren en uitvoeren van uw scripts.

Als u uw script opent en bewerkt in Visual Studio en andere IDE's, respecteert de tooling deze instelling bij het analyseren en controleren van uw script. Als de SDK niet wordt gevonden, moet u deze installeren op uw ontwikkelcomputer.

Op Linux- en andere Unix-systemen kunt u dit combineren met een shebang om ook een taalversie op te geven voor directe uitvoering van het script. Een eenvoudige shebang is script.fsx :

#!/usr/bin/env -S dotnet fsi

printfn "Hello, world"

Het script kan nu rechtstreeks worden uitgevoerd met script.fsx. U kunt dit combineren met een specifieke, niet-standaardtaalversie als volgt:

#!/usr/bin/env -S dotnet fsi --langversion:5.0

Notitie

Deze instelling wordt genegeerd door bewerkingsprogramma's, waarmee het script wordt geanalyseerd op basis van de nieuwste taalversie.

Verouderde functies verwijderen

Sinds F# 2.0 hebben sommige verouderde functies lang waarschuwingen gegeven. Als u deze functies in F# 6 gebruikt, krijgt u fouten tenzij u expliciet gebruikt /langversion:5.0. De functies die fouten geven zijn:

  • Meerdere algemene parameters met een naam voor het postfixtype, bijvoorbeeld (int, int) Dictionary. Dit wordt een fout in F# 6. In plaats daarvan moet de standaardsyntaxis Dictionary<int,int> worden gebruikt.
  • #indent "off". Dit wordt een fout.
  • x.(expr). Dit wordt een fout.
  • module M = struct … end . Dit wordt een fout.
  • Gebruik van invoer *.ml en *.mli. Dit wordt een fout.
  • Gebruik van (*IF-CAML*) of (*IF-OCAML*). Dit wordt een fout.
  • Gebruik van operatoren voor landinvoegsels , of asrlorlxorlsllsrals invoegseloperators. Dit zijn invoegwoorden in F# omdat ze infixtrefwoorden in OCaml waren en niet zijn gedefinieerd in FSharp.Core. Als u deze trefwoorden gebruikt, wordt er nu een waarschuwing verzonden.

Hiermee wordt F# RFC FS-1114 geïmplementeerd.