หมายเหตุ
การเข้าถึงหน้านี้ต้องได้รับการอนุญาต คุณสามารถลอง ลงชื่อเข้าใช้หรือเปลี่ยนไดเรกทอรีได้
การเข้าถึงหน้านี้ต้องได้รับการอนุญาต คุณสามารถลองเปลี่ยนไดเรกทอรีได้
Interpolated strings are strings that allow you to embed F# expressions into them. They are helpful in a wide range of scenarios where the value of a string may change based on the result of a value or expression.
Syntax
$"string-text {expr}"
$"string-text %format-specifier{expr}"
$@"string-text {expr}"
@$"string-text {expr}"
$"""string-text {"embedded string literal"}"""
$$"""string-text %%format-specifier{{expr}}"""
Remarks
Interpolated strings let you write code in "holes" inside of a string literal. Here's a basic example:
let name = "Phillip"
let age = 30
printfn $"Name: {name}, Age: {age}"
printfn $"I think {3.0 + 0.14} is close to {System.Math.PI}!"
The contents in between each {} brace pair can be any F# expression.
For string-valued interpolation in F# 11, an unformatted expression uses F#'s string conversion. If the expression evaluates to null, an empty string is used. Earlier compilers could optimize some string-only interpolations, but otherwise used printf formatting; see Native AOT and string-valued interpolation for formatting differences.
For typed interpolated strings with format specifiers (such as %s{expr} or %d{expr}), the conversion follows the rules defined for that specific format specifier.
To escape a {} brace pair, write two of them like so:
let str = $"A pair of braces: {{}}"
// "A pair of braces: {}"
Typed interpolated strings
Interpolated strings can also have F# format specifiers to enforce type safety.
let name = "Phillip"
let age = 30
printfn $"Name: %s{name}, Age: %d{age}"
// Error: type mismatch
printfn $"Name: %s{age}, Age: %d{name}"
In the previous example, the code mistakenly passes the age value where name should be, and vice/versa. Because the interpolated strings use format specifiers, this is a compile error instead of a subtle runtime bug.
Verbatim interpolated strings
F# supports verbatim interpolated strings in two ways:
Using $@ or @$ prefix
You can combine the interpolation prefix $ with the verbatim string prefix @ in any order. Verbatim strings ignore escape sequences (except for "" to represent a quotation mark) and can span multiple lines. This is especially useful when working with file paths or strings containing backslashes and quotes.
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"
Using triple quotes
F# also supports verbatim interpolated strings with triple quotes so that you can embed string literals without escaping.
let age = 30
printfn $"""Name: {"Phillip"}, Age: %d{age}"""
Format specifiers
Format specifiers can either be printf-style or .NET-style. Printf-style specifiers are those covered in plaintext formatting, placed before the braces. For example:
let pi = $"%0.3f{System.Math.PI}" // "3.142"
let code = $"0x%08x{43962}" // "0x0000abba"
The format specifier %A is particularly useful for producing diagnostic output of structured F# data.
let data = [0..4]
let output = $"The data is %A{data}" // "The data is [0; 1; 2; 3; 4]"
.NET-style specifiers are those usable with String.Format, placed after a : within the braces. For example:
let pi = $"{System.Math.PI:N4}" // "3.1416"
let now = $"{System.DateTime.UtcNow:``yyyyMMdd``}" // for example, "20220210"
If a .NET-style specifier contains an unusual character, then it can be escaped using double-backticks:
let nowDashes = $"{System.DateTime.UtcNow:``yyyy-MM-dd``}" // for example, "2022-02-10"
Aligning expressions in interpolated strings
You can left-align or right-align expressions inside interpolated strings with | and a specification of how many spaces. The following interpolated string aligns the left and right expressions to the left and right, respectively, by seven spaces.
printfn $"""|{"Left",-7}|{"Right",7}|"""
// |Left | Right|
Interpolated strings and FormattableString formatting
You can also apply formatting that adheres to the rules for 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."
Additionally, an interpolated string can also be type checked as a FormattableString via a type annotation:
let frmtStr = $"The speed of light is {speedOfLight:N3} km/s." : FormattableString
// Type: FormattableString
// The speed of light is 299,792.458 km/s.
Note that the type annotation must be on the interpolated string expression itself. F# does not implicitly convert an interpolated string into a FormattableString.
Extended syntax for string interpolation
Beginning with F# 8, when you work with text containing multiple {, } or % characters already, you can use extended string interpolation syntax to remove the need for escaping.
Triple quote string literals can start with multiple $ characters, which changes how many braces are required to open and close interpolation.
In these string literals, { and } characters don't need to be escaped:
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."""
The number of % characters needed for format specifiers is affected in the same way:
let percent = $$"""50% of 20 is %%.1f{{20m * 0.5m}}"""
// "50% of 20 is 10.0"
Native AOT and string-valued interpolation
To format text without a reflection-based formatting engine, use string-valued interpolation with plain or .NET-format holes:
let name = "Ada"
let score = 97.5
let message: string = $"{name}: {score:F1}"
printn message
// Ada: 97.5
F# 11 uses direct conversions and System.String.Concat for more string-valued interpolations. A .NET-format hole uses invariant String.Format and boxes its argument. These compiler changes support Native AOT without requiring the modern Core build; other application code can still need reflection.
Printf-style holes requiring printf formatting, such as %04d{number} or %A{record}, can still use the reflection-based path. Bare %s, %c, %d, %i, and %M holes retain their type checks and avoid printf formatting. Other specifiers, including %u, aren't covered by that optimization. An interpolation used as a PrintfFormat value is also distinct from one whose result type is string.
Culture and format compatibility
Plain holes use F#'s string conversion; .NET-format holes use invariant formatting. To produce localized output, select the culture explicitly:
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")
Check localized output when upgrading. FormattableString retains its arguments for later provider-based formatting instead of following this concatenation path.
Warning FS3884 identifies an unapplied function or delegate in an interpolation hole. Apply the function if you intended its result:
let weight () = 12.5m
let text: string = $"Weight: {weight ()} kg"
Write a value to standard output
To write a value without a printf format, FSharp.Core 11 adds print and printn. They use string conversion; printn adds a newline:
print "Parcels: "
printn 3
For structural %A output, use plaintext formatting.
Record and union output without reflection
With --reflectionfree, F# 11 can generate meaningful ToString implementations for records and unions instead of displaying only the type name:
type Reading = { Sensor: string; Value: int }
type Outcome = Recorded of Reading | Unavailable
let reading = { Sensor = "north"; Value = 12 }
printn reading
printn (Recorded reading)
The sample project enables the flag. Output differs from %A; field types also need suitable ToString implementations.