Novinky v F# 4.5

F# 4.5 přidává více vylepšení jazyka F#. Mnoho z těchto funkcí bylo přidáno dohromady, abyste mohli psát efektivní kód v jazyce F# a zároveň zajistit, aby byl tento kód bezpečný. To znamená, že při použití těchto konstruktorů přidáte do jazyka několik konceptů a značné množství analýzy kompilátoru.

Začínáme

F# 4.5 je k dispozici ve všech distribucích .NET Core a nástrojích sady Visual Studio. Začněte s jazykem F# a získejte další informace.

Span a byref-like struktury

Typ Span<T> zavedený v .NET Core umožňuje reprezentovat vyrovnávací paměti silným typem způsobem, který je nyní povolený v jazyce F# počínaje jazykem F# 4.5. Následující příklad ukazuje, jak můžete znovu použít funkci, která funguje s Span<T> různými reprezentacemi vyrovnávací paměti:

let safeSum (bytes: Span<byte>) =
    let mutable sum = 0
    for i in 0 .. bytes.Length - 1 do
        sum <- sum + int bytes[i]
    sum

// managed memory
let arrayMemory = Array.zeroCreate<byte>(100)
let arraySpan = new Span<byte>(arrayMemory)

safeSum(arraySpan) |> printfn "res = %d"

// native memory
let nativeMemory = Marshal.AllocHGlobal(100);
let nativeSpan = new Span<byte>(nativeMemory.ToPointer(), 100)

safeSum(nativeSpan) |> printfn "res = %d"
Marshal.FreeHGlobal(nativeMemory)

// stack memory
let mem = NativePtr.stackalloc<byte>(100)
let mem2 = mem |> NativePtr.toVoidPtr
let stackSpan = Span<byte>(mem2, 100)

safeSum(stackSpan) |> printfn "res = %d"

Důležitým aspektem je to, že span a další struktury podobné byref mají velmi pevnou statickou analýzu prováděnou kompilátorem, která omezuje jejich použití způsoby, které mohou být neočekávané. Toto je základní kompromis mezi výkonem, výrazností a bezpečností, která je zavedena v jazyce F# 4.5.

Reamped byrefs

Před jazykem F# 4.5 byly byrefy v jazyce F# nebezpečné a nespokojené pro mnoho aplikací. V jazyce F# 4.5 byly vyřešeny problémy se zvukem souvisejícími s funkcemi byref a byly použity také stejné statické analýzy pro struktury podobné rozsahu a byref.

inref'T<> a outref'T<>

Aby bylo možné znázorňovat pojem spravovaného ukazatele jen pro čtení, jen pro čtení a zápis, Finref<'T>outref<'T># 4.5 zavádí typy, které představují ukazatele jen pro čtení a jen pro zápis. Každý z nich má jinou sémantiku. Například nelze napsat do:inref<'T>

let f (dt: inref<DateTime>) =
    dt <- DateTime.Now // ERROR - cannot write to an inref!

Ve výchozím nastavení odvozování typu odvozuje spravované ukazatele tak, aby inref<'T> byly v souladu s neměnnou povahou kódu jazyka F#, pokud není něco již deklarováno jako proměnlivé. Pokud chcete vytvořit něco zapisovatelného, budete muset deklarovat typ jako mutable před předáním jeho adresy funkci nebo členu, který s ním manipuluje. Další informace najdete v tématu Byrefs.

Readonly – struktury

Počínaje jazykem F# 4.5 můžete anotovat strukturu IsReadOnlyAttribute takto:

[<IsReadOnly; Struct>]
type S(count1: int, count2: int) =
    member x.Count1 = count1
    member x.Count2 = count2

To vám neumožňuje deklarovat proměnlivý člen ve struktuře a generuje metadata, která umožňují F# a C# s ním při použití ze sestavení zacházet jako se čtením. Další informace najdete v tématu Jen pro čtení struktur.

Void pointers

Typ voidptr se přidá do F# 4.5, jak jsou následující funkce:

  • NativePtr.ofVoidPtr převodu ukazatele void na nativní int ukazatel
  • NativePtr.toVoidPtr převod nativního int ukazatele na ukazatel void

To je užitečné při spolupráci s nativní komponentou, která využívá ukazatele void.

Klíčové slovo match!

Klíčové match! slovo vylepšuje porovnávání vzorů v rámci výpočetního výrazu:

// Code that returns an asynchronous option
let checkBananaAsync (s: string) =
    async {
        if s = "banana" then
            return Some s
        else
            return None
    }

// Now you can use 'match!'
let funcWithString (s: string) =
    async {
        match! checkBananaAsync s with
        | Some bananaString -> printfn "It's banana!"
        | None -> printfn "%s" s
}

To vám umožní zkrátit kód, který často zahrnuje kombinování možností (nebo jiných typů) s výpočetními výrazy, jako je asynchronní. Další informace najdete v tématu shoda!.

Uvolněné požadavky na přesměrování v maticích, návazcích a sekvencích

Kombinování typů, kdy jeden může dědit z jiného uvnitř pole, seznamu a sekvence výrazů, tradičně vyžadoval přetypování jakéhokoli odvozeného typu do nadřazeného typu s :> nebo upcast. To je nyní uvolněné, což ukazuje následující:

let x0 : obj list  = [ "a" ] // ok pre-F# 4.5
let x1 : obj list  = [ "a"; "b" ] // ok pre-F# 4.5
let x2 : obj list  = [ yield "a" :> obj ] // ok pre-F# 4.5

let x3 : obj list  = [ yield "a" ] // Now ok for F# 4.5, and can replace x2

Odpočinek odsazení pro výrazy polí a seznamů

Před jazykem F# 4.5 bylo nutné při předání argumentů voláním metody příliš odsadit výrazy pole a seznamu. Toto se už nevyžaduje:

module NoExcessiveIndenting =
    System.Console.WriteLine(format="{0}", arg = [|
        "hello"
    |])
    System.Console.WriteLine([|
        "hello"
    |])