O F# 4.5 adiciona várias melhorias à linguagem F#. Muitos desses recursos foram adicionados para permitir que você escreva código eficiente em F# e, ao mesmo tempo, garanta que esse código seja seguro. Fazer isso significa adicionar alguns conceitos à linguagem e uma quantidade significativa de análise do compilador ao usar essas construções.
Começar agora
O F# 4.5 está disponível em todas as distribuições do .NET Core e nas ferramentas do Visual Studio. Comece a usar o F# para saber mais.
Estruturas semelhantes a span e byref
O Span<T> tipo introduzido no .NET Core permite que você represente buffers na memória de uma maneira fortemente tipada, o que agora é permitido em F# começando com F# 4.5. O exemplo a seguir mostra como você pode reutilizar uma função que opera em um Span<T> com diferentes representações de buffer:
F#
let safeSum (bytes: Span<byte>) =
letmutable sum = 0for i in0 .. bytes.Length - 1do
sum <- sum + int bytes[i]
sum
// managed memorylet arrayMemory = Array.zeroCreate<byte>(100)
let arraySpan = new Span<byte>(arrayMemory)
safeSum(arraySpan) |> printfn "res = %d"// native memorylet nativeMemory = Marshal.AllocHGlobal(100);
let nativeSpan = new Span<byte>(nativeMemory.ToPointer(), 100)
safeSum(nativeSpan) |> printfn "res = %d"
Marshal.FreeHGlobal(nativeMemory)
// stack memorylet mem = NativePtr.stackalloc<byte>(100)
let mem2 = mem |> NativePtr.toVoidPtr
let stackSpan = Span<byte>(mem2, 100)
safeSum(stackSpan) |> printfn "res = %d"
Um aspeto importante para isso é que Span e outras estruturas semelhantes a byref têm análises estáticas muito rígidas realizadas pelo compilador que restringem seu uso de maneiras que você pode achar inesperadas. Este é o compromisso fundamental entre desempenho, expressividade e segurança que é introduzido no F# 4.5.
Byrefs renovados
Antes do F# 4.5, Byrefs em F# eram inseguros e insalubres para inúmeras aplicações. Problemas de solidez em torno de byrefs foram abordados em F# 4.5 e a mesma análise estática feita para span e byref-like structs também foi aplicada.
inref'T<> e outref'T<>
Para representar a noção de um ponteiro gerenciado somente leitura, somente gravação e leitura/gravação, o F# 4.5 introduz os inref<'T>tipos , outref<'T> para representar ponteiros somente leitura e somente gravação, respectivamente. Cada um tem semânticas diferentes. Por exemplo, não é possível escrever em um inref<'T>arquivo :
F#
let f (dt: inref<DateTime>) =
dt <- DateTime.Now // ERROR - cannot write to an inref!
Por padrão, a inferência de tipo inferirá ponteiros gerenciados como inref<'T> estando de acordo com a natureza imutável do código F#, a menos que algo já tenha sido declarado como mutável. Para tornar algo gravável, você precisará declarar um tipo como mutable antes de passar seu endereço para uma função ou membro que o manipule. Para saber mais, consulte Byrefs.
[<IsReadOnly; Struct>]typeS(count1: int, count2: int) =
member x.Count1 = count1
member x.Count2 = count2
Isso impede que você declare um membro mutável no struct e emite metadados que permitem que F# e C# o tratem como somente leitura quando consumido de um assembly. Para saber mais, consulte Estruturas ReadOnly.
Ponteiros vazios
O voidptr tipo é adicionado ao F# 4.5, assim como as seguintes funções:
NativePtr.ofVoidPtr Para converter um ponteiro void em um ponteiro int nativo
NativePtr.toVoidPtr Para converter um ponteiro int nativo em um ponteiro void
Isso é útil ao interoperar com um componente nativo que faz uso de ponteiros vazios.
A palavra-chave match!
A match! palavra-chave melhora a correspondência de padrões quando está dentro de uma expressão computacional:
F#
// Code that returns an asynchronous optionlet checkBananaAsync (s: string) =
async {
if s = "banana"thenreturn Some s
elsereturn 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
}
Isso permite encurtar o código que geralmente envolve a mistura de opções (ou outros tipos) com expressões de computação, como assíncrono. Para saber mais, consulte match!.
Requisitos de upcasting relaxados em expressões de matriz, lista e sequência
A mistura de tipos em que um pode herdar de outro dentro de expressões de matriz, lista e sequência tradicionalmente exige que você atualize qualquer tipo derivado para seu tipo pai com :> ou upcast. Isto é agora relaxado, demonstrado da seguinte forma:
F#
let x0 : obj list = [ "a" ] // ok pre-F# 4.5let x1 : obj list = [ "a"; "b" ] // ok pre-F# 4.5let x2 : obj list = [ yield"a" :> obj ] // ok pre-F# 4.5let x3 : obj list = [ yield"a" ] // Now ok for F# 4.5, and can replace x2
Relaxamento de recuo para expressões de matriz e lista
Antes do F# 4.5, você precisava recuar excessivamente a matriz e listar expressões quando passadas como argumentos para chamadas de método. Isso não é mais necessário:
A origem deste conteúdo pode ser encontrada no GitHub, onde também pode criar e rever problemas e pedidos Pull. Para mais informações, consulte o nosso guia do contribuidor.
Comentários do .NET
O .NET é um projeto código aberto. Selecione um link para fornecer comentários:
F# é uma linguagem de programação de código aberto e multiplataforma que facilita a escrita de código sucinto, eficiente, robusto e prático. É uma linguagem de uso geral que permite criar muitos tipos diferentes de aplicativos, como API da Web, Desktop, IoT, jogos e muito mais.