Az F# 6 újdonságai

Az F# 6 számos fejlesztést tartalmaz az F# nyelvhez és az F# Interactivehoz. A .NET 6-ban jelenik meg.

A legújabb .NET SDK-t a .NET letöltési oldaláról töltheti le.

Első lépések

Az F# 6 minden .NET Core-disztribúcióban és Visual Studio-eszközben elérhető. További információ: Első lépések az F# használatával.

{...} feladat

Az F# 6 natív támogatást nyújt a .NET-feladatok F#-kódban való elkészítéséhez. Vegyük például a következő F#-kódot egy . NET-kompatibilis feladat:

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

Az F# 6 használatával ez a kód az alábbiak szerint írható újra.

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

Az F# 5 feladattámogatása a kiváló TaskBuilder.fs és Ply kódtárakon keresztül érhető el. A kódnak egyszerűnek kell lennie a beépített támogatásba való migrálása. Vannak azonban különbségek: a névterek és a típuskövetkezmények kissé eltérnek a beépített támogatás és a kódtárak között, és további típusjegyzetekre lehet szükség. Ha szükséges, akkor is használhatja ezeket a közösségi kódtárakat az F# 6 használatával, ha kifejezetten hivatkozik rájuk, és minden fájlban megnyitja a megfelelő névtereket.

A használat task {…} nagyon hasonló a használathoz async {…}. A használatnak task {…} több előnye async {…}is van:

  • A többletterhelés task {...} alacsonyabb, ami javíthatja a gyakori kód elérési útjainak teljesítményét, ahol az aszinkron munka gyorsan végrehajtható.
  • A léptető- és veremkövetések hibakeresése task {…} jobb.
  • A feladatokat váró vagy előállítandó .NET-csomagokkal való együttműködés egyszerűbb.

Ha már ismeri async {…}, az alábbiakat érdemes figyelembe vennie:

  • task {…} azonnal végrehajtja a feladatot az első várakozási pontra.
  • task {…} nem propagálja implicit módon a lemondási jogkivonatot.
  • task {…} nem végez implicit lemondási ellenőrzéseket.
  • task {…} nem támogatja az aszinkron tailcallokat. Ez azt jelenti, hogy a rekurzív használata return! .. verem túlcsordulását eredményezheti, ha nem történik közbeeső aszinkron várakozás.

Általában érdemes megfontolni az új kódban való használatot task {…}async {…} , ha feladatokat használó .NET-kódtárakkal dolgozik, és nem támaszkodik az aszinkron kódszkreditálásokra vagy implicit lemondási jogkivonat propagálására. A meglévő kódban csak akkor váltson át task {…} , ha áttekintette a kódot, hogy ne támaszkodjon a korábban említett jellemzőkre async {…}.

Ez a funkció implementálja az F# RFC FS-1097-et.

Egyszerűbb indexelési szintaxis a expr[idx]

Az F# 6 lehetővé teszi a expr[idx] gyűjtemények indexelését és szeletelését.

Az F# 5-höz hasonlóan az F# indexelési szintaxisként is használható expr.[idx] . A használat expr[idx] engedélyezése az F#-t tanuló felhasználók ismételt visszajelzésén alapul, vagy az F# első alkalommal való megtekintésén alapul, hogy a pont-jelölés indexelés használata szükségtelen eltérést jelent a szabványos iparági gyakorlattól.

Ez nem kompatibilitástörő változás, mert alapértelmezés szerint a rendszer nem ad ki figyelmeztetést a használata során expr.[idx]. A kód pontosítását javaslatokat tevő tájékoztató üzenetek azonban ki lesznek bocsátva. Opcionálisan további tájékoztató üzeneteket is aktiválhat. Aktiválhat például egy opcionális tájékoztató figyelmeztetést (/warnon:3566) a expr.[idx] jelölés jelentési felhasználásának megkezdéséhez. További információ: Indexer Notation.

Az új kódban javasoljuk az indexelés szintaxisának expr[idx] rendszeres használatát.

Ez a funkció implementálja az F# RFC FS-1110-et.

Részleges aktív minták strukturálási ábrázolásai

Az F# 6 kibővíti az "aktív minták" funkciót a részleges aktív minták opcionális strukturálási ábrázolásaival. Ez lehetővé teszi, hogy egy attribútum használatával egy részleges aktív mintát korlátozva adjon vissza egy értékbeállítást:

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

Az attribútum használata kötelező. A használati helyeken a kód nem változik. A nettó eredmény az, hogy a foglalások csökkennek.

Ez a funkció az F# RFC FS-1039-et implementálja.

Túlterhelt egyéni műveletek számítási kifejezésekben

Az F# 6 lehetővé teszi a CustomOperationAttribute használatát a túlterhelt metódusokon.

Fontolja meg a számítási kifejezésszerkesztő contentalábbi használatát:

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

Itt az body egyéni művelet különböző típusú argumentumokat használ. Ezt a következő szerkesztő implementációja támogatja, amely túlterhelést használ:

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

Ez a funkció az F# RFC FS-1056-ot implementálja.

"as" minták

Az F# 6-ban a minta jobb oldala as most már minta lehet. Ez akkor fontos, ha egy típusteszt erősebb típust adott egy bemenetnek. Vegyük például a következő kódot:

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)

Minden minta esetében a bemeneti objektum típustesztelése történik. A minta jobb oldali része as mostantól egy további minta lehet, amely maga is megfelelhet az objektumnak az erősebb típusnál.

Ez a funkció az F# RFC FS-1105-öt implementálja.

Behúzás szintaxisának korrektúrái

Az F# 6 számos inkonzisztenciát és korlátozást távolít el a behúzásérzékeny szintaxis használata során. Lásd: RFC FS-1108. Ez az F#-felhasználók által az F# 4.0 óta kiemelt 10 jelentős problémát oldja meg.

Az F# 5-ben például a következő kód engedélyezett:

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

A következő kód azonban nem engedélyezett (figyelmeztetést eredményezett):

let c = [
    1
    2
]

Az F# 6-ban mindkettő engedélyezett. Ez egyszerűbbé és könnyebben elsajátíthatóvá teszi az F#-t. Az F# közösség közreműködője , Hadrian Tang vezette ezt az utat, beleértve a funkció figyelemre méltó és rendkívül értékes szisztematikus tesztelését.

Ez a funkció az F# RFC FS-1108-at implementálja.

További implicit konverziók

Az F# 6-ban aktiváltuk az RFC FS-1093-ban leírt további "implicit" és "típusvezérelt" konverziók támogatását.

Ez a változás három előnnyel jár:

  1. Kevesebb explicit felcímkésítésre van szükség
  2. Kevesebb explicit egész szám konvertálása szükséges
  3. Első osztályú támogatás a következőhöz: . NET-stílusú implicit konverziók hozzáadva

Ez a funkció az F# RFC FS-1093-at implementálja.

További implicit felkonvertálások

Az F# 6 további implicit felkonvertálásokat valósít meg. Az F# 5-ös és korábbi verzióiban például felcímkézésre volt szükség a visszatérési kifejezéshez egy olyan függvény implementálásakor, amelyben a kifejezések különböző altípusokkal rendelkeztek a különböző ágakon, még akkor is, ha egy típusjegyzet jelen volt. Vegye figyelembe a következő F# 5 kódot:

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

Itt a feltételes számítás TextReaderStreamReader ágai és a felcímkésítés hozzáadva, hogy mindkét ág streamReader típusú legyen. Az F# 6-ban ezek a felcímkék automatikusan hozzáadódnak. Ez azt jelenti, hogy a kód egyszerűbb:

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

Opcionálisan engedélyezheti, hogy a figyelmeztetés /warnon:3388 minden ponton megjelenítsen egy további implicit felcímkézést, az implicit konverziókra vonatkozó opcionális figyelmeztetésekben leírtak szerint.

Implicit egész számkonvertálások

Az F# 6-ban a 32 bites egész számok 64 bites egész számokra szélesednek, ha mindkét típus ismert. Vegyük például egy tipikus API-alakzatot:

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

Az F# 5-ben az int64 egész számkonstansait kell használni:

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

vagy

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

Az F# 6-ban a szélesítés automatikusan int32 megtörténik a int64int32nativeintforrás és int32 a doublecél típusának a típuskövetkeztetés során történő ismertsége esetén. Így az olyan esetekben, mint az előző példák, int32 konstansok használhatók:

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

A változás ellenére az F# a legtöbb esetben továbbra is a numerikus típusok explicit szélesítését használja. Az implicit szélesítés például nem vonatkozik más numerikus típusokra, például int8 vagy int16– vagy – float32 a forrás vagy a float64cél típus ismeretlen típusára. Azt is engedélyezheti, hogy a figyelmeztetés /warnon:3389 minden pontnál implicit numerikus szélesítést jelenítsen meg, az implicit konverziók opcionális figyelmeztetéseiben leírtak szerint.

Első osztályú támogatás a következőhöz: . NET-stílusú implicit konverziók

Az F# 6-ban a .NET "op_Implicit" konverziói automatikusan lesznek alkalmazva az F# kódban metódusok hívásakor. Az F# 5-ben például a .NET API-k XML-hez való használatakor kellett használni XName.op_Implicit :

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

Az F# 6-ban a rendszer automatikusan alkalmazza a konverziókat az argumentumkifejezésekre, op_Implicit ha a forráskifejezéshez és a céltípushoz típusok érhetők el:

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

Engedélyezheti, hogy a figyelmeztetés /warnon:3395 figyelmeztetést jelenítsen meg minden pontonop_Implicit, amikor a metódusargumentumok szélesítést használnak, az implicit konverziókra vonatkozó opcionális figyelmeztetésekben leírtak szerint.

Feljegyzés

Az F# 6 első kiadásában ez a figyelmeztetési szám volt /warnon:3390. Ütközés miatt a figyelmeztetési szám később a következőre frissült /warnon:3395: .

Opcionális figyelmeztetések implicit konverziókhoz

A típusalapú és implicit konverziók rosszul kommunikálhatnak a típuskövetkeztetéssel, és nehezebben értelmezhető kódhoz vezethetnek. Ezért léteznek bizonyos enyhítések annak érdekében, hogy ez a funkció ne legyen visszaélve az F#-kóddal. Először is, a forrás- és céltípusnak erősen ismertnek kell lennie, és nem merül fel kétértelműség vagy további típuskövetkezmény. Másodszor, a bejelentkezési figyelmeztetések aktiválhatók az implicit konverziók bármilyen használatának jelentésére, alapértelmezés szerint egy figyelmeztetéssel:

  • /warnon:3388 (további implicit felcímkés)
  • /warnon:3389 (implicit numerikus szélesítés)
  • /warnon:3391 (op_Implicit nem metódusargumentumokon alapértelmezés szerint)
  • /warnon:3395 (op_Implicit metódusargumentumokban)

Ha csapata be szeretné tiltani az implicit konverziók összes használatát, megadhatja /warnaserror:3388azt is, /warnaserror:3389/warnaserror:3391és /warnaserror:3395.

Bináris számok formázása

Az F# 6 hozzáadja a mintát a %B bináris számformátumok rendelkezésre álló formátumjelölőihez. Vegye figyelembe a következő F#-kódot:

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

Ez a kód a következő kimenetet nyomtatja ki:

173
1111011

Ez a funkció az F# RFC FS-1100-et implementálja.

Használaton alapuló kötések elvetése

Az F# 6 lehetővé teszi _ a kötések use használatát, például:

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

Ez a funkció az F# RFC FS-1102-et implementálja.

InlineIfLambda

Az F#-fordító tartalmaz egy optimalizálót, amely kódrészletezést végez. Az F# 6-ban hozzáadtunk egy új deklaratív funkciót, amely lehetővé teszi, hogy a kód opcionálisan jelezze, hogy ha egy argumentumot lambda függvénynek határoznak meg, akkor az argumentumnak mindig beágyazottnak kell lennie a hívási helyeken.

Vegyük például a következő iterateTwice függvényt egy tömb bejárásához:

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]

Ha a hívás helye a következő:

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

Ezután a kód alining és más optimalizálások után a következő lesz:

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]

Az F#korábbi verzióitól eltérően ez az optimalizálás az érintett lambda kifejezés méretétől függetlenül érvényesül. Ez a funkció a ciklusok regisztrációjának feloldására és a hasonló átalakítások megbízhatóbb megvalósítására is használható.

A bejelentkezési figyelmeztetés (/warnon:3517alapértelmezés szerint kikapcsolva) bekapcsolható, hogy jelezze a kód azon helyeit, ahol InlineIfLambda az argumentumok nem kötődnek a lambda kifejezésekhez a hívási helyeken. Normál helyzetekben ezt a figyelmeztetést nem szabad engedélyezni. Bizonyos típusú nagy teljesítményű programozás esetén azonban hasznos lehet biztosítani, hogy az összes kód beágyazott és összesimított legyen.

Ez a funkció implementálja az F# RFC FS-1098-at.

Újra felhasználható kód

Az task {…} F# 6 támogatása egy RFC FS-1087 kódnevű alapra épül. Az újrahasználható kód egy technikai funkció, amellyel sokféle nagy teljesítményű aszinkron és hozamú állapotú gépeket hozhat létre.

További gyűjteményfüggvények

Az FSharp.Core 6.0.0 öt új műveletet ad hozzá az alapvető gyűjteményfüggvényekhez. Ezek a függvények a következők:

  • List/Array/Seq.insertAt
  • Lista/Tömb/Seq.removeAt
  • List/Array/Seq.updateAt
  • List/Array/Seq.insertManyAt
  • List/Array/Seq.removeManyAt

Ezek a függvények mindegyike másolási és frissítési műveleteket hajt végre a megfelelő gyűjteménytípuson vagy -sorozaton. Ez a művelettípus a "funkcionális frissítés" egyik formája. A függvények használatára vonatkozó példákért tekintse meg a megfelelő dokumentációt, például : List.insertAt.

Vegyük például egy elmish stílusban írt egyszerű "Todo List" alkalmazás modelljét, üzenetét és frissítési logikáját. Itt a felhasználó interakcióba lép az alkalmazással, üzeneteket generál, és a update függvény feldolgozza ezeket az üzeneteket, létrehozva egy új modellt:

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 }

Ezekkel az új függvényekkel a logika egyértelmű és egyszerű, és csak nem módosítható adatokra támaszkodik.

Ez a funkció implementálja az F# RFC FS-1113-at.

A térkép kulcsokkal és értékekkel rendelkezik

Az FSharp.Core 6.0.0-ban a Map típus mostantól támogatja a Kulcsok és értékek tulajdonságokat. Ezek a tulajdonságok nem másolja az alapul szolgáló gyűjteményt.

Ez a funkció az F# RFC FS-1113-ban van dokumentálva.

További intrinsics for NativePtr

Az FSharp.Core 6.0.0 új belső elemeket ad hozzá a NativePtr modulhoz:

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

A többi függvényhez NativePtrhasonlóan ezek a függvények beágyazottak, és használatuk figyelmeztetéseket ad ki, hacsak nem /nowarn:9 használják őket. Ezeknek a függvényeknek a használata nem felügyelt típusokra korlátozódik.

Ez a funkció az F# RFC FS-1109-ben van dokumentálva.

További numerikus típusok egységjegyzetekkel

Az F# 6-ban az alábbi típusok vagy rövidítési aliasok mostantól támogatják a mértékegység-széljegyzeteket. Az új kiegészítések félkövér színben jelennek meg:

F# alias CLR-típus
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

Egy aláíratlan egész számot például az alábbiak szerint jegyzetelhet:

[<Measure>]
type days

let better_age = 3u<days>

Ez a funkció az F# RFC FS-1091-ben van dokumentálva.

Tájékoztató figyelmeztetések ritkán használt szimbolikus operátorokhoz

Az F# 6 olyan finom útmutatást ad hozzá, amely normalizálja a , , , és decr az F# 6 és azon túl használatát:=. incr! Ezek az operátorok és függvények olyan tájékoztató üzeneteket eredményeznek, amelyek arra kérik, hogy cserélje le a kódot a Value tulajdonság explicit használatára.

Az F#-programozásban referenciacellák használhatók a halom által lefoglalt mutable-regiszterekhez. Bár néha hasznosak, a modern F#-kódoláshoz ritkán van szükség rájuk, mert let mutable ehelyett használhatók. Az F#-magtár két operátort := és ! két függvényt incr tartalmaz, amelyek decr kifejezetten referenciahívásokhoz kapcsolódnak. Ezeknek az operátoroknak a jelenléte a szükségesnél központibbá teszi a referenciacellákat az F#-programozásban, így az összes F#-programozónak ismernie kell ezeket az operátorokat. Továbbá az ! operátor könnyen összetéveszthető a not C# és más nyelvek műveletével, ami a kód fordítása során esetlegesen apró hibák forrása.

Ennek a változásnak az az oka, hogy csökkenti az F# programozó által ismert operátorok számát, és ezáltal egyszerűsíti az F# használatát a kezdők számára.

Vegyük például a következő F# 5 kódot:

let r = ref 0

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

Először is, a referenciacellákra ritkán van szükség a modern F#-kódolásban, ahogyan let mutable az általában is használható:

let mutable r = 0

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

Hivatkozáscellák használata esetén az F# 6 tájékoztató figyelmeztetést ad ki, amely arra kéri, hogy módosítsa az utolsó sort r.Value <- r.Value + 1a hivatkozáscellákra, és további útmutatást nyújt a referenciacellák megfelelő használatáról.

let r = ref 0

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

Ezek az üzenetek nem figyelmeztetések; ezek az IDE és a fordító kimenetében megjelenő "tájékoztató üzenetek". Az F# visszafelé kompatibilis marad.

Ez a funkció az F# RFC FS-1111-et implementálja.

F# eszközkészlet: A .NET 6 az alapértelmezett szkriptelés a Visual Studióban

Ha megnyit vagy végrehajt egy F#-szkriptet (.fsx) a Visual Studióban, a szkript alapértelmezés szerint a .NET 6 használatával, 64 bites végrehajtással lesz elemezve és végrehajtva. Ez a funkció előzetes verzióban jelent meg a Visual Studio 2019 későbbi kiadásaiban, és alapértelmezés szerint engedélyezve van.

A .NET-keretrendszer szkriptek engedélyezéséhez válassza az Eszközök>beállításai>F# Eszközök>F# Interaktív lehetőséget. Állítsa a .NET Core-szkriptelést hamisra, majd indítsa újra az F# Interaktív ablakot. Ez a beállítás a szkriptek szerkesztésére és a szkriptek végrehajtására is hatással van. Ha engedélyezni szeretné a 32 bites végrehajtást .NET-keretrendszer szkripteléshez, állítsa a 64 bites F# Interactive értéket hamisra. A .NET Core-szkriptek esetében nincs 32 bites lehetőség.

F# eszközkészlet: Az F#-szkriptek SDK-verziójának rögzítése

Ha egy .NET SDK-beállítást tartalmazó global.json fájlt tartalmazó könyvtárban hajt végre szkriptetdotnet fsi, akkor a .NET SDK felsorolt verziójával hajtja végre és szerkesztheti a szkriptet. Ez a funkció az F# 5 későbbi verzióiban érhető el.

Tegyük fel például, hogy van egy szkript egy könyvtárban, amely a következő global.json fájllal rendelkezik, amely egy .NET SDK verziószabályzatot határoz meg:

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

Ha most futtatja a szkriptet dotnet fsia könyvtárból, a rendszer tiszteletben tartja az SDK-verziót. Ez egy hatékony funkció, amellyel "zárolhatja" a szkriptek fordításához, elemzéséhez és végrehajtásához használt SDK-t.

Ha a szkriptet a Visual Studióban és más azonosítókban nyitja meg és szerkessze, az eszköz ezt a beállítást fogja figyelembe venni a szkript elemzésekor és ellenőrzésekor. Ha az SDK nem található, telepítenie kell azt a fejlesztőgépre.

Linux és más Unix rendszereken ezt kombinálhatja egy shebanggal , hogy a szkript közvetlen végrehajtásához egy nyelvi verziót is megadhat. Egy egyszerű shebang a következőhöz script.fsx :

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

printfn "Hello, world"

A szkript most már közvetlenül is végrehajtható a következővel: .script.fsx> Ezt kombinálhatja egy adott, nem alapértelmezett nyelvi verzióval, például a következővel:

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

Feljegyzés

Ezt a beállítást a szerkesztőeszközök figyelmen kívül hagyják, amely a szkriptet a legújabb nyelvi verziót feltételezve elemzi.

Régi funkciók eltávolítása

Az F# 2.0 óta néhány elavult örökölt funkció már régóta figyelmeztetéseket adott. Ha ezeket a funkciókat az F# 6-ban használja, az csak akkor ad hibát, ha kifejezetten használja /langversion:5.0. A hibákat okozó funkciók a következők:

  • Több általános paraméter postfix típusú névvel, például (int, int) Dictionary. Ez az F# 6-ban hibává válik. Ehelyett a standard szintaxist Dictionary<int,int> kell használni.
  • #indent "off". Ez hibává válik.
  • x.(expr). Ez hibává válik.
  • module M = struct … end . Ez hibává válik.
  • Bemenetek *.ml és *.mli. Ez hibává válik.
  • A vagy (*IF-OCAML*)a (*IF-CAML*) . Ez hibává válik.
  • landA , lor, lxor, lsl, lsrvagy asr infix operátorok használata. Ezek az F# fájlban található infix kulcsszavak, mivel az OCamlben infix kulcsszavak voltak, és nem az FSharp.Core-ban vannak definiálva. Ezek a kulcsszavak mostantól figyelmeztetést adnak ki.

Ez az F# RFC FS-1114-et implementálja.