挿入文字列は、F# 式を埋め込むことができる 文字列 です。 これらは、値または式の結果に基づいて文字列の値が変更される可能性があるさまざまなシナリオで役立ちます。
構文
$"string-text {expr}"
$"string-text %format-specifier{expr}"
$@"string-text {expr}"
@$"string-text {expr}"
$"""string-text {"embedded string literal"}"""
$$"""string-text %%format-specifier{{expr}}"""
注釈
挿入文字列を使用すると、文字列リテラル内の "穴" にコードを記述できます。 基本的な例を次に示します。
let name = "Phillip"
let age = 30
printfn $"Name: {name}, Age: {age}"
printfn $"I think {3.0 + 0.14} is close to {System.Math.PI}!"
各 {} 中かっこペアの間の内容には、任意の F# 式を指定できます。
F# 11 の文字列値補間の場合、書式設定されていない式は F# の string 変換を使用します。 式が nullと評価された場合は、空の文字列が使用されます。 以前のコンパイラでは文字列のみの補間をいくつか最適化できましたが、それ以外の場合は printf 書式を使用しました。書式設定の違いについては、 ネイティブ AOT と文字列値補間 を参照してください。
書式指定子 ( %s{expr} や %d{expr}など) を持つ型指定された補間文字列の場合、変換は、その特定の書式指定子に対して定義された規則に従います。
{}中かっこペアをエスケープするには、次のように 2 つを記述します。
let str = $"A pair of braces: {{}}"
// "A pair of braces: {}"
型指定された挿入文字列
挿入文字列には、型の安全性を強制する F# 書式指定子を含めることもできます。
let name = "Phillip"
let age = 30
printfn $"Name: %s{name}, Age: %d{age}"
// Error: type mismatch
printfn $"Name: %s{age}, Age: %d{name}"
前の例では、コードは誤ってageする必要があるname値を渡します。その逆も同様です。 挿入文字列では書式指定子が使用されるため、これは実行時の微妙なバグではなくコンパイル エラーです。
逐語的な補間文字列
F# では、次の 2 つの方法で逐語的な補間文字列がサポートされています。
$@または@$ プレフィックスの使用
補間プレフィックス $ と逐語的な文字列プレフィックス @ を任意の順序で組み合わせることができます。 逐語的な文字列はエスケープ シーケンスを無視し (引用符を表す "" を除く)、複数行にまたがることができます。 これは、円記号と引用符を含むファイル パスまたは文字列を操作する場合に特に便利です。
let name = "Alice"
let path = @"C:\Users\Alice\Documents"
// Using $@ prefix
printfn $@"User {name} has files in: {path}"
// Using @$ prefix (also valid)
printfn @$"User {name} has files in: {path}"
// Embedding quotes - use "" to represent a single "
let message = $@"He said ""{name}"" is here"
三重引用符の使用
F# では、エスケープせずに文字列リテラルを埋め込むことができるように、三重引用符で囲まれた逐語的な補間文字列もサポートされています。
let age = 30
printfn $"""Name: {"Phillip"}, Age: %d{age}"""
書式指定子
書式指定子は、printf スタイルまたは .NET スタイル。 Printf スタイルの指定子は、中かっこの前に配置された プレーンテキストの書式設定でカバーされる指定子です。 例えば次が挙げられます。
let pi = $"%0.3f{System.Math.PI}" // "3.142"
let code = $"0x%08x{43962}" // "0x0000abba"
書式指定子 %A は、構造化 F# データの診断出力を生成する場合に特に便利です。
let data = [0..4]
let output = $"The data is %A{data}" // "The data is [0; 1; 2; 3; 4]"
.NET スタイルの指定子は、中かっこ内のString.Formatの後に配置される、:で使用できる指定子です。 例えば次が挙げられます。
let pi = $"{System.Math.PI:N4}" // "3.1416"
let now = $"{System.DateTime.UtcNow:``yyyyMMdd``}" // for example, "20220210"
If a .NET スタイル指定子には通常とは異なる文字が含まれています。その後、二重バックティックを使用してエスケープできます。
let nowDashes = $"{System.DateTime.UtcNow:``yyyy-MM-dd``}" // for example, "2022-02-10"
挿入文字列での式の配置
挿入文字列内の式は、 | とスペースの数の指定を使用して左揃えまたは右揃えにできます。 次の補間文字列は、左右の式をそれぞれ 7 つのスペースで左右に配置します。
printfn $"""|{"Left",-7}|{"Right",7}|"""
// |Left | Right|
挿入文字列と FormattableString 書式設定
また、 FormattableStringの規則に従った書式を適用することもできます。
let speedOfLight = 299792.458
printfn $"The speed of light is {speedOfLight:N3} km/s."
// "The speed of light is 299,792.458 km/s."
さらに、挿入文字列は、型注釈を使用して FormattableString として型チェックすることもできます。
let frmtStr = $"The speed of light is {speedOfLight:N3} km/s." : FormattableString
// Type: FormattableString
// The speed of light is 299,792.458 km/s.
型注釈は、挿入文字列式自体に存在する必要があることに注意してください。 F# では、補間された文字列は暗黙的に FormattableStringに変換されません。
文字列補間の拡張構文
F# 8 以降では、既に複数の {、 } 、または % 文字を含むテキストを操作する場合は、拡張文字列補間構文を使用してエスケープの必要性を排除できます。
三重引用符文字列リテラルは、複数の $ 文字で始まり、補間を開いたり閉じたりするために必要な中かっこの数を変更できます。
これらの文字列リテラルでは、 { 文字と } 文字をエスケープする必要はありません。
let str = $$"""A string containing some {curly braces} and an {{"F#" + " " + "expression"}}."""
// "A string containing some {curly braces} and an F# expression."
let another = $$$"""A string with pairs of {{ and }} characters and {{{ "an F# expression" }}}."""
// "A string with pairs of {{ and }} characters and an F# expression."""
書式指定子に必要な % 文字の数も、同じように影響を受けます。
let percent = $$"""50% of 20 is %%.1f{{20m * 0.5m}}"""
// "50% of 20 is 10.0"
ネイティブ AOT と文字列値補間
リフレクション ベースの書式設定エンジンを使用せずにテキストを書式設定するには、プレーンまたは.NET形式の穴を含む文字列値補間を使用します。
let name = "Ada"
let score = 97.5
let message: string = $"{name}: {score:F1}"
printn message
// Ada: 97.5
F# 11 では、直接変換と System.String.Concat を使用して、より多くの文字列値補間を行います。 .NET形式の穴では、不変のString.Formatを使用し、その引数をボックス化します。 これらのコンパイラの変更では、最新のコア ビルドを必要とせずに ネイティブ AOT がサポートされます。他のアプリケーション コードでもリフレクションが必要な場合があります。
%04d{number}や%A{record}など、printf 形式の書式設定を必要とする Printf スタイルの穴では、リフレクション ベースのパスを引き続き使用できます。 ベア %s、 %c、 %d、 %i、 %M の穴は、型チェックを保持し、printf の書式設定を回避します。
%uを含む他の指定子は、その最適化の対象になりません。
PrintfFormat値として使用される補間も、結果の型がstringされた補間とは異なります。
カルチャと形式の互換性
プレーンホールはF#のstring変換を使用します。.NET形式のホールでは、インバリアント書式設定が使用されます。 ローカライズされた出力を生成するには、カルチャを明示的に選択します。
open System.Globalization
let value = 12.5m
let machineText: string = $"{value:F2}"
let displayText =
value.ToString("F2", CultureInfo.GetCultureInfo("fr-FR"))
assert (machineText = "12.50")
assert (displayText = "12,50")
アップグレード時にローカライズされた出力を確認します。
FormattableString では、この連結パスに従う代わりに、後でプロバイダー ベースの書式設定を行う引数が保持されます。
警告 FS3884 は、補間ホール内の未適用の関数またはデリゲートを識別します。 結果を意図した場合は、関数を適用します。
let weight () = 12.5m
let text: string = $"Weight: {weight ()} kg"
標準出力に値を書き込む
printf 形式を使用せずに値を書き込むには、FSharp.Core 11 によって print と printnが追加されます。
string変換を使用します。printnは改行を追加します。
print "Parcels: "
printn 3
構造 %A 出力には、 プレーンテキスト形式を使用します。
リフレクションを使用しないレコードと共用体の出力
--reflectionfreeでは、F# 11 では、型名のみを表示するのではなく、レコードと共用体に対して意味のあるToString実装を生成できます。
type Reading = { Sensor: string; Value: int }
type Outcome = Recorded of Reading | Unavailable
let reading = { Sensor = "north"; Value = 12 }
printn reading
printn (Recorded reading)
サンプル プロジェクトでフラグが有効になります。 出力は %Aとは異なります。フィールド型には適切な ToString 実装も必要です。
こちらも参照ください
.NET