Cordas interpoladas

Strings interpoladas são strings que permitem incorporar expressões F# nelas. Eles são úteis em uma ampla variedade de cenários onde o valor de uma cadeia de caracteres pode mudar com base no resultado de um valor ou expressão.

Sintaxe

$"string-text {expr}"
$"string-text %format-specifier{expr}"
$@"string-text {expr}"
@$"string-text {expr}"
$"""string-text {"embedded string literal"}"""
$$"""string-text %%format-specifier{{expr}}"""

Observações

Strings interpoladas permitem que você escreva código em "buracos" dentro de um literal de cadeia de caracteres. Aqui está um exemplo básico:

let name = "Phillip"
let age = 30
printfn $"Name: {name}, Age: {age}"

printfn $"I think {3.0 + 0.14} is close to {System.Math.PI}!"

O conteúdo entre cada {} par de chaves pode ser qualquer expressão F#.

Para interpolação de valores de cadeia em F# 11, uma expressão não formatada usa a conversão de string F#. Se a expressão for avaliada como null, uma cadeia de caracteres vazia será usada. Compiladores anteriores conseguiam otimizar algumas interpolações apenas de strings, mas de resto usavam formatação printf; ver Native AOT e interpolação de valores em strings para diferenças de formatação.

Para cadeias de caracteres interpoladas tipadas com especificadores de formato (como %s{expr} ou %d{expr}), a conversão segue as regras definidas para esse especificador de formato específico. Para escapar de um {} par de cintas, escreva duas delas assim:

let str = $"A pair of braces: {{}}"
// "A pair of braces: {}"

Strings interpoladas digitadas

As cadeias de caracteres interpoladas também podem ter especificadores de formato F# para reforçar a segurança do tipo.

let name = "Phillip"
let age = 30

printfn $"Name: %s{name}, Age: %d{age}"

// Error: type mismatch
printfn $"Name: %s{age}, Age: %d{name}"

No exemplo anterior, o código passa por engano o age valor onde name deveria estar e vice/versa. Como as cadeias de caracteres interpoladas usam especificadores de formato, este é um erro de compilação em vez de um bug de tempo de execução sutil.

Cordas interpoladas verbatim

O F# suporta strings interpoladas textuais de duas maneiras:

Usando $@ ou @$ prefixo

Você pode combinar o prefixo $ de interpolação com o prefixo @ de cadeia de caracteres literal em qualquer ordem. As cadeias de caracteres verbatinas ignoram sequências de escape (exceto para "" representar aspas) e podem abranger várias linhas. Isso é especialmente útil ao trabalhar com caminhos de arquivo ou cadeias de caracteres contendo barras invertidas e aspas.

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"

Usando aspas triplas

F# também suporta strings interpoladas textuais com aspas triplas para que você possa incorporar literais de cadeia de caracteres sem escapar.

let age = 30

printfn $"""Name: {"Phillip"}, Age: %d{age}"""

Especificadores de formato

Os especificadores de formato podem ser no estilo printf ou . Estilo NET. Os especificadores de estilo printf são aqueles cobertos em formatação de texto simples, colocados antes das chaves. Por exemplo:

let pi = $"%0.3f{System.Math.PI}"  // "3.142"
let code = $"0x%08x{43962}"  // "0x0000abba"

O especificador %A de formato é particularmente útil para produzir saída de diagnóstico de dados F# estruturados.

let data = [0..4]
let output = $"The data is %A{data}"  // "The data is [0; 1; 2; 3; 4]"

. Os especificadores de estilo NET são aqueles utilizáveis com String.Format, colocados depois de um : dentro dos aparelhos. Por exemplo:

let pi = $"{System.Math.PI:N4}"  // "3.1416"
let now = $"{System.DateTime.UtcNow:``yyyyMMdd``}" // for example, "20220210"

Se um arquivo . O especificador estilo NET contém um caractere incomum, então ele pode ser escapado usando double-backticks:

let nowDashes = $"{System.DateTime.UtcNow:``yyyy-MM-dd``}" // for example, "2022-02-10"

Alinhando expressões em cadeias de caracteres interpoladas

Você pode alinhar expressões à esquerda ou à direita dentro de cadeias de caracteres interpoladas com | e uma especificação de quantos espaços. A sequência interpolada a seguir alinha as expressões esquerda e direita à esquerda e à direita, respectivamente, por sete espaços.

printfn $"""|{"Left",-7}|{"Right",7}|"""
// |Left   |  Right|

Strings interpoladas e FormattableString formatação

Você também pode aplicar uma formatação que siga as regras para 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."

Além disso, uma cadeia de caracteres interpolada também pode ser verificada como um tipo através de FormattableString uma anotação de tipo:

let frmtStr = $"The speed of light is {speedOfLight:N3} km/s." : FormattableString
// Type: FormattableString
// The speed of light is 299,792.458 km/s.

Observe que a anotação de tipo deve estar na própria expressão de cadeia de caracteres interpolada. F# não converte implicitamente uma cadeia de caracteres interpolada em um FormattableStringarquivo .

Sintaxe estendida para interpolação de cadeia de caracteres

A partir do F# 8, quando você trabalha com texto que contém vários {caracteres ou }% caracteres, você pode usar a sintaxe de interpolação de cadeia de caracteres estendida para remover a necessidade de escapar.

Os literais de cadeia de aspas triplas podem começar com vários $ caracteres, o que altera quantas chaves são necessárias para abrir e fechar a interpolação. Nestes literais de cadeia de caracteres, { e } caracteres não precisam ser escapados:

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."""

O número de caracteres necessários para especificadores de % formato é afetado da mesma maneira:

let percent = $$"""50% of 20 is %%.1f{{20m * 0.5m}}"""
// "50% of 20 is 10.0"

Interpolação AOT nativa e com valores de cadeia

Para formatar texto sem um motor de formatação baseado em reflexão, use interpolação de valores em cadeia de caracteres com buracos em formato simples ou .NET:

let name = "Ada"
let score = 97.5
let message: string = $"{name}: {score:F1}"
printn message
// Ada: 97.5

F# 11 utiliza conversões diretas e System.String.Concat para mais interpolações de valores de corda. Um buraco no formato .NET usa invariante String.Format e bloqueia o seu argumento. Estas alterações ao compilador suportam AOT nativo sem exigir a versão Core moderna; outro código de aplicação ainda pode necessitar de reflexão.

Buracos ao estilo printf que requerem formatação printf, como %04d{number} ou %A{record}, ainda podem usar o caminho baseado em reflexão. Os %sburacos nus mantêm %M%c%d%ias verificações de tipo e evitam a formatação printf. Outros especificadores, incluindo %u, não são cobertos por essa otimização. Uma interpolação usada como PrintfFormat valor também é distinta daquela cujo tipo de resultado é string.

Compatibilidade cultural e de formatos

Os buracos simples usam a conversão de string F#; os buracos no formato .NET usam formatação invariante. Para produzir uma saída localizada, selecione explicitamente a cultura:

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")

Verifica a saída localizada ao atualizar. FormattableString mantém os seus argumentos para uma formatação futura baseada em fornecedores em vez de seguir este caminho de concatenação.

Aviso: FS3884 identifica uma função ou delegado não aplicado num buraco de interpolação. Aplique a função se pretendia o seu resultado:

let weight () = 12.5m
let text: string = $"Weight: {weight ()} kg"

Escrever um valor para a saída padrão

Para escrever um valor sem formato printf, o FSharp.Core 11 adiciona print e printn. Usam string conversão; printn adiciona uma nova linha:

print "Parcels: "
printn 3

Para saída estrutural %A , use formatação de texto simples.

Saída de gravação e união sem reflexão

Com --reflectionfree, F# 11 pode gerar implementações significativas ToString para registos e uniões em vez de mostrar apenas o nome do tipo:

type Reading = { Sensor: string; Value: int }
type Outcome = Recorded of Reading | Unavailable

let reading = { Sensor = "north"; Value = 12 }
printn reading
printn (Recorded reading)

O projeto de exemplo ativa a bandeira. A saída difere de %A; os tipos de campo também necessitam de implementações adequadas ToString .

Ver também