F# 字符串插值
最后修改日期:2025 年 5 月 17 日
在本文中,我们将探讨 F# 中的字符串插值。
F# 中的字符串插值提供了一种简洁的方式将表达式嵌入到字符串字面量中。插值字符串以 $ 为前缀,并包含用 {} 包裹的表达式。此功能允许动态构建字符串,从而更轻松地创建格式化字符串,而无需繁琐的字符串连接或格式化函数。
基本字符串插值
F# 字符串插值允许直接在字符串中嵌入变量和表达式
let name = "John Doe"
let age = 34
printfn $"{name} is {age} years old"
let now = System.DateTime.Now
printfn $"""Today is {now.DayOfWeek}, it's {now.ToString("HH:mm")}"""
此示例展示了简单的变量插值和日期时间格式化。$ 前缀标记了一个插值字符串,其中包含用 {} 包裹的表达式。
λ dotnet fsi basic_interpolation.fsx John Doe is 34 years old Today is Sunday, it's 11:58
类型化字符串插值
F# 支持类型化的插值字符串,带有格式说明符以确保类型安全
let name = "John Doe"
let age = 34
printfn $"Name: %s{name}, Age: %d{age}"
let price = 49.99
let quantity = 3
printfn $"Total: %f{price * float quantity}"
格式说明符(字符串为 %s,整数为 %d,浮点数为 %f)可确保类型安全和正确的格式。
λ dotnet fsi typed_interpolation.fsx Name: John Doe, Age: 34 Total: 149.970000
格式字符串
插值字符串支持 .NET 的数字和日期格式字符串
let now = System.DateTime.Now
printfn $"Short date: {now:d}"
printfn $"Long date: {now:D}"
printfn $"Short time: {now:t}"
printfn $"Long time: {now:T}"
let value = 1234.5678
printfn $"Currency: {value:C}"
printfn $"Scientific: {value:E2}"
printfn $"Fixed-point: {value:F2}"
标准的 .NET 格式说明符可在插值表达式中使用。
λ dotnet fsi format_strings.fsx Short date: 19. 1. 2024 Long date: Friday, January 19, 2024 Short time: 11:19 Long time: 11:19:22 Currency: $1,234.57 Scientific: 1.23E+003 Fixed-point: 1234.57
对齐和填充
可以使用对齐说明符在插值字符串中对齐值
type User = { FirstName: string; LastName: string; Salary: int }
let users = [
{ FirstName = "John"; LastName = "Doe"; Salary = 1230 }
{ FirstName = "Lucy"; LastName = "Novak"; Salary = 670 }
{ FirstName = "Ben"; LastName = "Walter"; Salary = 2050 }
]
for user in users do
let name = $"{user.FirstName} {user.LastName}"
printfn $"|{name,-15}|{user.Salary,8}|"
负数对齐表示左对齐,正数表示右对齐。数字指定总宽度。
λ dotnet fsi alignment.fsx |John Doe | 1230| |Lucy Novak | 670| |Ben Walter | 2050|
插值中的表达式
复杂的表达式可以嵌入到插值字符串中
let x = 5
let y = 10
printfn $"Sum: {x + y}"
printfn $"Product: {x * y}"
printfn $"""Comparison: {if x < y then "x < y" else "x >= y"}"""
let numbers = [1..5]
printfn $"Count: {numbers.Length}, Sum: {List.sum numbers}"
任何有效的 F# 表达式都可以在插值花括号内使用。
λ dotnet fsi expressions.fsx Sum: 15 Product: 50 Comparison: x < y Count: 5, Sum: 15
多行插值字符串
F# 支持使用三引号语法进行多行插值字符串
let name = "Alice"
let score = 95
let grade = if score >= 90 then "A" else "B"
let status = if score >= 70 then "PASS" else "FAIL"
let message = $"""
Report for {name}:
- Score: {score}
- Grade: {grade}
- Status: {status}
"""
printfn "%s" message
三引号会保留字符串字面量中的缩进和换行符。
λ dotnet fsi multiline.fsx Report for Alice: - Score: 95 - Grade: A - Status: PASS
逐字插值字符串
在 F# 中,插值字符串 $"..." 允许变量替换,而逐字字符串 @"..." 则会保留反斜杠等转义序列。
要正确格式化路径,请单独使用用于反斜杠的逐字字符串和用于替换的插值字符串
let path = @"C:\Users\John" // Verbatim string (preserves backslashes)
let file = "document.txt"
let fullPath = $"Full path: {path}\\{file}" // Double backslash to escape in interpolated string
printfn "%s" fullPath
逐字字符串对于处理文件路径、正则表达式模式和转义序列很有用,而插值字符串则简化了变量替换。
λ dotnet fsi verbatim.fsx Full path: C:\Users\John\document.txt
带集合的插值字符串
集合可以在插值字符串中进行处理
let fruits = ["apple"; "banana"; "orange"]
printfn $"""Fruits: {String.concat ", " fruits}"""
printfn $"Count: {List.length fruits}"
printfn $"First: {List.head fruits}"
let numbers = [1..5]
printfn $"Sum: {List.sum numbers}, Avg: {List.averageBy float numbers}"
集合操作可以在插值表达式中自然地工作。
λ dotnet fsi collections.fsx Fruits: apple, banana, orange Count: 3 First: apple Sum: 15, Avg: 3.0
条件格式化
条件逻辑可以在插值字符串中使用
let items = [
"ring", 2
"lamp", 1
"chair", 3
]
for (name, count) in items do
printfn $"""{count} {name}{if count = 1 then "" else "s"}"""
let temp = 22.5
printfn $"""Temperature: {temp}°C ({if temp > 20.0 then "Warm" else "Cool"})"""
括号有助于将条件运算符与格式字符串分开。
λ dotnet fsi conditional.fsx 2 rings 1 lamp 3 chairs Temperature: 22.5°C (Warm)
最佳实践
遵循这些指南以实现有效的字符串插值
// 1. Use typed interpolation for safety
let userId = "A123"
let attempts = 3
printfn $"User %s{userId} has %d{attempts} attempts left"
// 2. Keep complex logic outside strings
let calculateTotal price qty = price * float qty
let itemPrice = 12.99
let quantity = 5
printfn $"Total: {calculateTotal itemPrice quantity:C}"
// 3. Format for readability
let data = [(1, "A"); (2, "B"); (3, "C")]
for (id, value) in data do
printfn $"|{id,3}|{value,-5}|"
// 4. Prefer interpolation over concatenation
let name = "Alice"
let age = 30
// Good:
printfn $"Name: {name}, Age: {age}"
// Avoid:
printfn "%s" ("Name: " + name + ", Age: " + string age)
F# 字符串插值提供了一种强大的方法来创建包含嵌入式表达式的字符串。$ 前缀可轻松插入变量,而类型化插值(%s、%d)可确保类型安全。多行和逐字字符串可处理复杂的格式需求,使字符串构建更清晰、更易于维护。