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 meest recente .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. Overweeg bijvoorbeeld de volgende F#-code om een te maken. 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 er kunnen enkele aanvullende typeaantekeningen nodig zijn. 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 van async {…}. Het gebruik task {…} heeft verschillende voordelen ten opzichte async {…}van :

  • De prestaties van task {…} zijn veel beter.
  • Foutopsporing voor stap- en stack-traceringen voor task {…} is beter.
  • Werken met .NET-pakketten die taken verwachten of produceren, is eenvoudiger.

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

  • task {…} voert de taak onmiddellijk uit tot 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 recursief gebruik return! .. kan leiden tot stackoverloop als er geen tussenliggende asynchrone wachttijden zijn.

Over het algemeen kunt u overwegen om over async {…} te gebruiken task {…} in nieuwe code als u werkt met .NET-bibliotheken die gebruikmaken van taken en als u niet afhankelijk bent van asynchrone code tailcalls of impliciete annuleringstokens. In bestaande code moet u alleen overschakelen naar task {…} zodra u uw 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.

Eenvoudiger indexeringssyntaxis met expr[idx]

F# 6 staat de syntaxis expr[idx] toe voor het indexeren en segmenteren van verzamelingen.

Tot en met F# 5 is F# gebruikt expr.[idx] als indexeringssyntaxis. Het toestaan van het gebruik van expr[idx] is gebaseerd op herhaalde feedback van degenen die F# leren of F# voor het eerst zien dat het gebruik van puntnotatie-indexering overkomt als een onnodige afwijking van de standaardpraktijk in de branche.

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

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

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

Struct-weergaven 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 de toewijzingen worden verlaagd.

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

Overbelaste aangepaste bewerkingen in rekenexpressies

Met F# 6 kunt u interfaces met standaard implementaties gebruiken.

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 gebruikt de body aangepaste bewerking een wisselend 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. Bekijk bijvoorbeeld 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 mag nu een ander patroon zijn, dat zelf overeenkomt met het object op het sterkere type.

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

Revisies van de syntaxis van inspringingen

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. Dit maakt F# eenvoudiger en gemakkelijker te leren. De inzender van de F#-community Hadrian Tang heeft hierin de leiding genomen, inclusief opmerkelijke en zeer waardevolle systematische tests 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 brengt drie voordelen met zich mee:

  1. Er zijn minder expliciete upcasts vereist
  2. Er zijn minder expliciete conversies van 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 upcastconversies

F# 6 implementeert aanvullende impliciete upcast-conversies. 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. Bekijk 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 respectievelijk en TextReaderStreamReader en de upcast toegevoegd om beide vertakkingen het type StreamReader te geven. 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 desgewenst de waarschuwing /warnon:3388 inschakelen om een waarschuwing weer te geven op elk moment dat er een extra impliciete upcast wordt gebruikt, zoals wordt beschreven in Optionele waarschuwingen voor impliciete conversies.

Impliciete conversies van gehele getallen

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

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

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

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

of

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

In F# 6 vindt de verbreding automatisch plaats voor int32 naar int64, int32 naar nativeinten int32 naar double, wanneer zowel het bron- als het doeltype bekend zijn tijdens typedeductie. In gevallen zoals in de vorige voorbeelden int32 kunnen letterlijke waarden worden gebruikt:

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

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

Eersteklas ondersteuning voor . Impliciete conversies in NET-stijl

In F# 6 worden .NET op_Implicit-conversies 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 op argumentexpressies wanneer er typen beschikbaar zijn voor bronexpressie en doeltype:

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

U kunt de waarschuwing /warnon:3395 desgewenst inschakelen om een waarschuwing weer te geven bij elk punt op_Implicit dat conversies worden verbreed bij methodeargumenten, zoals beschreven in Optionele waarschuwingen voor impliciete conversies.

Notitie

In de eerste release 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 zijn er enkele oplossingen om ervoor te zorgen dat deze functie niet wordt misbruikt in F#-code. Ten eerste moet zowel het bron- als het doeltype sterk bekend zijn, zonder dubbelzinnigheid of aanvullende typedeductie. Ten tweede kunnen opt-in-waarschuwingen worden geactiveerd om elk gebruik van impliciete conversies te melden, waarbij standaard één waarschuwing is ingeschakeld:

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

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

Opmaak voor binaire getallen

F# 6 voegt het %B patroon toe 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 bij gebruiksbindingen

F# 6 staat toe _ om te worden gebruikt in een use binding, bijvoorbeeld:

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 eventueel kan aangeven dat, als een argument wordt vastgesteld als een lambda-functie, dat argument zelf altijd moet worden inlined op aanroepsites.

Overweeg bijvoorbeeld 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 is:

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

Na het inlinen en andere optimalisaties wordt de code:

let arr = [| 1.. 100 |]
let mutable sum = 0
for j = 0 to array.Length-1 do
    sum <- array[i] + x
for j = 0 to array.Length-1 do
    sum <- array[i] + x

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

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

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

Hervatbare code

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

Aanvullende verzamelingsfuncties

Met FSharp.Core 6.0.0 worden vijf nieuwe bewerkingen toegevoegd 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 voor voorbeelden van het gebruik van deze functies, bijvoorbeeld List.insertAt.

Denk bijvoorbeeld aan het model, de bericht- en updatelogica voor een eenvoudige takenlijsttoepassing 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 intrinsieke kenmerken voor NativePtr

FSharp.Core 6.0.0 voegt nieuwe intrinsieke functies 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 in NativePtrzijn deze functies inlined en het gebruik ervan geeft waarschuwingen, tenzij /nowarn:9 wordt 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 ondersteunen de volgende typen of type-afkortingaliassen nu 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 geheel getal zonder teken:

[<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 :=, !, incren decr in F# 6 en hoger wordt gedenormaliseerd. Het gebruik van deze operators en functies produceert informatieve berichten die u vragen om uw code te vervangen door expliciet gebruik van de Value eigenschap.

In F#-programmering kunnen referentiecellen worden gebruikt voor aan heap toegewezen veranderlijke 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 die decr specifiek betrekking hebben op 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 fouten bij het vertalen van code.

De reden voor deze wijziging is om het aantal operators te verminderen dat de F#-programmeur moet kennen en zo F# voor beginners te vereenvoudigen.

Neem bijvoorbeeld de volgende F# 5-code:

let r = ref 0

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

Ten eerste 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, geeft F# 6 een informatieve waarschuwing waarin u wordt gevraagd om de laatste regel te wijzigen in r.Value <- r.Value + 1, 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; het 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 het uitvoeren van scripts 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 scripting wilt inschakelen, selecteert u Extra>Opties>F# Hulpprogramma's>F# Interactief. Stel .NET Core-scripts gebruiken in op false en start het venster F# Interactive opnieuw. Deze instelling is van invloed op zowel het bewerken van scripts als het uitvoeren van scripts. Als u 32-bits uitvoering voor .NET Framework scripting wilt inschakelen, 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 waarin een .NET SDK-versiebeleid wordt opgegeven:

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

Als u het script nu uitvoert met behulp van dotnet fsi, vanuit deze map, wordt de SDK-versie in acht genomen. 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, wordt deze instelling door het hulpprogramma gerespecteerd 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 voor script.fsx is:

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

printfn "Hello, world"

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

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

Notitie

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

Verouderde functies verwijderen

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

  • Meerdere algemene parameters met behulp van een naam van het type postfix, 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 land, lor, lxor, lsl, lsr, of asr als infix-operators. Dit zijn infixtrefwoorden in F# omdat ze infix-trefwoorden waren in OCaml en niet zijn gedefinieerd in FSharp.Core. Als u deze trefwoorden gebruikt, wordt er nu een waarschuwing weergegeven.

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