F# — статически типизированный мультипарадигмальный язык программирования из семейства языков .NET от корпорации Microsoft. Во многом F# испытал влияние OCaml, являясь, по сути, его продвинутой реализацией для платформы .NET. Компилятор языка открыт, а его код доступен на GitHub.
Самое заметное изменение в этом релизе — увеличение минорной версии языка сразу на четыре единицы. Это было сделано для синхронизации версий языка и библиотеки FSharp.Core:
- Было: F# 4.1; FSharp.Core 4.4.1.0
- Стало: F# 4.5; FSharp.Core 4.5.x.0
Причины этого исторические, но конечный результат заключается в том, что он довольно запутан для пользователей F# в течение длительного времени. Итак, это было исправлено.
Side-by-side развёртка компиляторов F# в Visual Studio
SDK компилятора F# использует для установки глобальное местоположение на вашем компьютере. Любая последующая установка Visual Studio будет перезаписывать это местоположение, если версии были одинаковыми (например, для исправлений ошибок). Кроме того, чтобы не создавать беспорядок на вашем компьютере, Visual Studio удалит установку, которую она разместила там при удалении. Это привело к множеству проблем для людей на протяжении многих лет. Например, при установке бета‐версий Visual Studio рядом с релизной версией, бета‐версия могла перезаписать компилятор F#, что заставляло релизную версию Visual Studio использовать бета‐версию компилятора F#!
Для F# 4.5 версия SDK для компилятора будет 10.2. Дополнительные установки Visual Studio (или другие наборы инструментов) не будут выбирать эту более высокую версию SDK.
Поддержка Span
Самое крупное изменение в F# 4.5 — это набор инструментов для поддержки Span, представленном в .NET Core 2.1. Этот набор включает:
- Тип
voidptr
. - Функции
NativePtr.ofVoidPtr
иNativePtr.toVoidPtr
в FSharp.Core. - Типы
inref<'T>
иoutref<'T>
, которые являются read‐only и write‐only версиямиbyref<'T>
соответственно. - Возможность создания
IsByRefLike
структур (напримерSpan<'T>
иReadOnlySpan<'T>
). - Возможность создания
IsReadOnly
структур. - И другое.
Основными целями этого являются:
- Предложение способов создания высокопроизводительного кода на F#.
- Полное совпадение с нововведениями в .NET Core.
- Улучшение генерации кода.
Правила безопасности для byref’ов
Как упоминалось ранее, byref’ы и byref‐like структуры довольно ограничены в том, как их можно использовать. Это связано с тем, что их цель заключается в том, чтобы сделать код низкого уровня безопасным и предсказуемым. Это возможно только путем ограничения использования определенных типов в соответствующих контекстах и анализа вашего кода для обеспечения надежности и корректности.
Краткое изложение некоторых правил:
- Значение let-bound не может содержать ссылку на себя.
- byref‐like структуры не могут быть экземплярами или статическими членами класса или нормальной структуры.
- byref‐like структуры не могут быть захвачены каким‐либо замыканием.
- byref‐like структуры не могут использоваться как параметр типа.
Напоминаем, что Span<'T>
и ReadOnlySpan<'T>
являются byref‐like структурами и подчиняются этим правилам.
Новое ключевое слово: match!
Computation Expressions (аналог do‐нотации) теперь поддерживают ключевое слово match!
, убирая этим бойлерплейт, существующий сегодня в большом количестве кода.
Вот этот код:
// Code that returns an asynchronous option
let checkBananaAsync (s: string) =
async {
if s = "banana" then
return Some s
else
return None
}
// Need to bind the result of checkBananaAsync before pattern matching
let funcWithString (s: string) =
async {
let! r = checkBananaAsync s
match r with
| Some bananaString -> printfn "It's banana!"
| None -> printfn "%s" s
}
Теперь может быть переписан так:
// 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
}
Это было реализовано John’ом Wostenberg’ом, членом F# OSS community.
Улучшенный трейсинг Async
В F# 4.5 и FSharp.Core 4.5.0 трейсинг Async в computation expressions улучшен:
- Отчётные номера строк теперь соответствуют ошибочному коду пользователя.
- Непользовательский код больше не возвращается.
Дополнительные улучшения в FSharp.Core
В дополнение к улучшенному трейсингу Async имеются некоторые небольшие улучшения в FSharp.Core:
-
Map.TryGetValue
(RFC). -
ValueOption<'T>
(RFC). -
FuncConvert.FromFunc
иFuncConvert.FromAction
, принимающие экземплярыFunc<'A,' B>
иAction<'A,' B>
из C#‐кода (RFC).
Этот код иллюстрирует первые два улучшения:
//
// Map.TryGetValue
//
let mp = Map.ofList [("doot", 1); ("beef", 2); ("hoopty", 3)]
match mp.TryGetValue "doot" with
| (true, value) -> printfn "Value: %A" value
| (false, _) -> printfn "No value found!"
//
// ValueOption
//
let isBanana (str: string) =
if str = "banana" then
ValueSome str
else
ValueNone
match isBanana "banana" with
| ValueSome s -> printfn s
| ValueNone -> printfn "Not a banana :("
Добавление API FuncConvert не так полезно для F#‐only кода, но оно помогает во взаимодействии C# и F#, позволяя использовать «современные» C#‐структуры: например, Action и Func.
Улучшения производительности
В этом выпуске были сделаны улучшения производительности F# и инструментов для F#, на некоторые из которых очень сильно повлияло сообщество. Некоторые из этих улучшений включают:
- Удаление ≈2.2% от memory allocations в компиляторе F#.
- Сравнение bools (используемое везде) теперь использует быстрый вариант сравнения. Это было реализовано Василием Кириченко.
- Значительные улучшения производительности IntelliSense в Visual Studio.
- Производительность IntelliSense для очень больших файлов F# (≥10k строк кода) улучшилась примерно в два раза, благодаря усилиям сообщества во главе с Василием Кириченко, Steffen’ом Forkmann’ом и Gauthier’ом Segay’ем.
Как обновиться
Получить F# 4.5 можно двумя путями:
- Вместе с последним .NET SDK (≥2.1.400).
- С обновлением Visual Studio 2017 версии 15.8.
>>> Подробности