F# 6.0 の新機能
What’s new in F# 6 の情報になります。
F# 6.0 が追加され次第、こちらの更新していきます。
task コンピュテーション式
C# などの他の .NET 言語との相互運用性を高めるために Task<’T> 専用のコンピュテーション式が追加されました。
F# 5.0 までは async {...}
内で Async.AwaitTask
で Task<’T> を Async<’T> に変換しつつ利用する必要がありました。
F# 6.0 からは task {...}
で直接扱えるようになりました。
インデックス構文のシンプル化
F# でインデックスを利用したアクセスをする場合には expr.[idx]
が構文として提供されてきました。
F# 6.0 では C# のように .
を使わない expr[idx]
が新たにサポートされるようになりました。
アクティブ パターンの構造体サポート
アクティブ パターンの戻り値は構造体でも問題ないような場合でも、参照型でしか表現できなかったためシナリオによってはコストが割高でした。
F# 6.0 では構造体として表現できるようになりました。
利用方法は簡単で、今までのアクティブパターンに [<return: Struct>]
属性を追加するだけです。
コンピュテーション式のカスタム オペレーションのオーバーロード サポート
F# 5.0 で preview 提供されていたコンピュテーション式のカスタム オペレーションのオーバーロード サポートが正式導入されました。
as パターンの機能拡張
F# 5.0 までは as パターンの右辺でパターンマッチを使用できませんでした。
F# 6.0 からは as パターンの右辺でパターンマッチを利用できるようになりました。
インデントルールの統一
F# 5.0 までは使用する機能によってインデントルールが異なることで F# の学習コストが上がってしまっていました。
F# 6.0 からはその差異を埋めることで、より統一的なインデントルールを提供しています。
use バインディングの破棄
F# 6.0 では use バインディングでも _
で束縛できるようになりました。
2 進数表現用のフォーマット指定子の追加
F# 6.0 では、数値を 2 進数表現するためのフォーマット指定子が追加されました。
InlineIfLambda 属性の追加
F# 6.0 では、ラムダ式 を引数で指定する場合に inline 化されるべきであることを宣言するための属性が追加されました。
呼び出し方は特に今までと変わりません。
上記の例は以下のように展開されます。
この inline 化はラムダ式のサイズに関係なく適用されます。
リストと配列の生成式のパフォーマンスとデバッグの改善
F# 6.0 では、リストと配列の生成式が最大 4 倍高速になりました。
また、個々の行にブレークポイントを設定できるようになりました。
暗黙的な型変換の緩和
F# 6.0 では、RFC FS-1093 で記載されているような暗黙的な型変換が追加サポートされました。
この変更により、以下の 3 つのことが実現されます。
- 明示的なアップキャストが減る
- int32 型の明示的な型変換が減る
- .NET スタイルの暗黙的な型変換のサポート
- 明示的なアップキャストが減る
F# 5.0 以前では、関数の宣言で型アノテーションが指定されていても、分岐で異なるサブタイプの戻り値を返す関数を実装する場合には戻り値にアップキャストが必要でした。
F# 6.0 からは、自動でアップキャストされるようになりました。
- int32 の明示的な型変換が減る
F# 6.0 では、 int32 → int64 や int32 → double など、変換元の型と変換先の型が両方わかっていれば暗黙的な型変換が行われるようになりました。
ただし、変換先の型の表現できる範囲が int32 よりも広い必要があります。また、 int8 や int16、float などの int32 以外の型の場合や、変換元や変換先の型が不明な場合には暗黙的な型変換は自動で行われません。
- .NET スタイルの暗黙的な型変換のサポート
F# 5.0 までは .NET の暗黙的な型変換実装(op_Implicit)を利用して、明示的な型変換をする必要がありました。
F# 6.0 からは自動で op_Implicit を呼び出すようになります。
immutable コレクション用モジュールのアップデート
FSharp.Core 6.0.0.0 からコレクション用モジュール (List / Array / Seq モジュール) に以下の 5 つの関数が追加されました。
- List / Array / Seq.insertAt
- List / Array / Seq.removeAt
- List / Array / Seq.updateAt
- List / Array / Seq.insetManyAt
- List / Array / Seq.removeManyAt
これらの操作は、対象のコレクションに対してコピーと更新を行うため、元のコレクションに変更が加わりません。そのため、immutable なデータのみに依存することになり、ロジックが明確かつシンプルになります。
各関数の使用方法についてはリンク先のドキュメントを参照してください。
Map<’Key, ‘Value> への Keys / Values プロパティの追加
FSharp.Core 6.0.0.0 から Map<’Key, ‘Value> へ Keys と Values が追加されました。
これらのプロパティは元のコレクションをコピーして返すものではないので注意が必要です。
NativePtr モジュールのアップデート
FSharp.Core 6.0.0.0 から NativePtr モジュールに以下の 8 つの関数が追加されました。
- NativePtr.nullPtr
- NativePtr.isNullPtr
- NativePtr.initBlock
- NativePtr.clear
- NativePtr.copy
- NativePtr.copyBlock
- NativePtr.ofILSigPtr
- NativePtr.toILSigPtr
上記の関数は NativePtr モジュールの他の関数と同様、インライン化されています。
また、/nowarn:9 が使われていない限り警告が発生します。
これらの関数はアンマネージド型にしか利用できません。
測定単位が使える数値型を拡大
F# 5.0 までは測定単位で利用できる数値型は float / float32 / decimal / 符号付き整数値型 に限られていました。
F# 6.0 からはそれらに加えて nativeint / unativeint / 符号無し整数値型 と、double や single などの型のエイリアスがサポートされるようになりました。
F# Alias | CLR Types |
---|---|
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.UInt64 |
nativeint+ | System.IntPtr |
unativeint+ | System.UIntPtr |
※ 追加でサポートされるようになった型には (+) を付与しています。
利用頻度の低い演算子の使用を削減する提案
F# ではヒープに割り当てられた mutable レジスタに参照セルを使えます。
この機能が便利なときも稀にありますが、最近の F# のコーディングでは let mutable を使えるので、必要になることはほとんどありません。
F# のコアライブラリには、参照呼び出しに関する :=
と !
の 2 つの演算子と、decr
と incr
の 2 つの関数があります。これらの演算子があることで、F# プログラミングにおいて参照セルが必要以上に中心的なものとなってしまっており、すべての F# プログラマがこれらの演算子を知っていなければならない状況となってしまっています。
さらに !
演算子は C# などの他の言語を知っている人が F# を学び始めた場合に not
演算子と混同されやすく、バグの原因となったり学習コストを高めたりする原因になる可能性があります。
その結果、F# 6.0 では :=
/ !
/ decr
/ incr
の使用を非正規化するソフトガイダンスを行いました。
これらの演算子や関数を使用すると、Value プロパティを明示的に使用したコードに置き換えるように求める情報メッセージが表示されます。
レガシー機能の削除
F# 2.0 で非推奨とされた機能について、F# 6.0 で削除されることになりました。
削除される機能 | 代替方法など |
---|---|
(int, int) Dictionary |
Dictionary<int, int> |
#indent "off" |
- |
module M = struct ... end |
- |
*.ml / *.mli の使用 |
- |
(*IF-CAML*) / (*IF-OCAML*) |
- |
land / lor / lxor / lsl / lsr / asr の使用 |
エラーではなく警告 |
F# tool - パイプラインのデバッグ
パイプライン演算子の各ステップに対してブレークポイントの設定やステッピング デバッグができるようになりました。
// ステッピング デバッグ
// ブレークポイントの設定
F# tool - デバッガで表示されるシャドウイングされた値
F# ではシャドウイングが許されているので、例えば以下のようなコードが許容されています。
新しい F# tool では以下のようにシャドウイングされる前とされた後の値が表示されるようになりました。
F# tool - In-memory cross-project referencing!
F# 6.0 からは同一ソリューションに存在する F# プロジェクトと C# プロジェクト間の作業がよりシンプルで信頼性の高いものとなりました。
In-memory cross-project referencing により、ソリューション上の C# プロジェクトに変更を加えた際に再コンパイルすることなく、直ちに F# プロジェクトに反映されます。
F# tool - F# Script で利用する既定フレームワークが .NET Core / .NET に
Visual Studio で F# Script (.fsx) を開いたり、実行したりすると、デフォルトで 64bit の .NET Core / .NET を使用するようになりました。
F# tool - Visual Studio と Visual Studio Code の .NET Interactive 対応
.NET Interactive Notebooks を使うことで、F# や C# でノートブックスタイルのプログラミングを行えます。
最近のリリースでは、 Visual Studio Code での優れたサポートに加えて、多くの改善が行われています。
Visual Studio 2022 向けの拡張機能 Notebook Editor については コチラ で発表されました。
System.Text.Json が F# の一般的な型をサポート
F# 6.0 以降、 System.Text.Json が F# の一般的な型をサポートするようになりました。