Stringhe interpolate

Le stringhe interpolate sono stringhe che consentono di incorporare espressioni F# in esse. Sono utili in un'ampia gamma di scenari in cui il valore di una stringa può cambiare in base al risultato di un valore o di un'espressione.

Sintassi

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

Osservazioni:

Le stringhe interpolate consentono di scrivere codice in "fori" all'interno di un valore letterale stringa. Ecco un esempio di base:

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

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

Il contenuto in tra ogni {} coppia di parentesi graffe può essere qualsiasi espressione F#.

Per l'interpolazione con valori di stringa in F# 11, un'espressione non formattata usa la conversione di string F#. Se l'espressione restituisce null, viene usata una stringa vuota. I compilatori precedenti potevano ottimizzare alcune interpolazioni di sola stringa, ma in caso contrario usavano la formattazione printf; vedere AOT nativo e interpolazione con valori di stringa per le differenze di formattazione.

Per le stringhe interpolate tipate con identificatori di formato (ad esempio %s{expr} o %d{expr}), la conversione segue le regole definite per l'identificatore di formato specifico. Per eseguire l'escape di una {} coppia di parentesi graffe, scriverne due come segue:

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

Stringhe interpolate tipate

Le stringhe interpolate possono anche avere identificatori di formato F# per applicare la sicurezza dei tipi.

let name = "Phillip"
let age = 30

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

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

Nell'esempio precedente il codice passa erroneamente il age valore in cui name deve essere e viceversa. Poiché le stringhe interpolate usano identificatori di formato, si tratta di un errore di compilazione anziché di un bug di runtime sottile.

Stringhe interpolate verbatim

F# supporta stringhe interpolate verbatim in due modi:

Uso $@ o @$ prefisso

È possibile combinare il prefisso $ di interpolazione con il prefisso @ di stringa verbatim in qualsiasi ordine. Le stringhe verbatim ignorano le sequenze di escape (ad eccezione di "" per rappresentare una virgoletta) e possono estendersi su più righe. Ciò è particolarmente utile quando si utilizzano percorsi di file o stringhe contenenti barre rovesciata e virgolette.

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"

Uso di virgolette triple

F# supporta anche stringhe interpolate verbatim con virgolette triple in modo da poter incorporare valori letterali stringa senza escape.

let age = 30

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

Identificatori di formato

Gli identificatori di formato possono essere di tipo printf o . Stile NET. Gli identificatori di stile Printf sono quelli coperti nella formattazione in testo non crittografato, posizionati prima delle parentesi graffe. Per esempio:

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

L'identificatore di %A formato è particolarmente utile per produrre l'output di diagnostica dei dati F# strutturati.

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

. Gli identificatori di stile NET sono utilizzabili con String.Format, posizionati dopo una : all'interno delle parentesi graffe. Per esempio:

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

Se è un oggetto . L'identificatore di stile NET contiene un carattere insolito, quindi può essere preceduto da un carattere di escape tramite double-backticks:

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

Allineamento delle espressioni nelle stringhe interpolate

È possibile allineare a sinistra o allineare a destra le espressioni all'interno di stringhe interpolate con | e una specifica del numero di spazi. La stringa interpolata seguente allinea le espressioni di sinistra e destra rispettivamente a sinistra e a destra, di sette spazi.

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

Stringhe interpolate e FormattableString formattazione

È anche possibile applicare la formattazione conforme alle regole per 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."

Inoltre, una stringa interpolata può anche essere controllata come tipo FormattableString tramite un'annotazione di 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.

Si noti che l'annotazione del tipo deve trovarsi nell'espressione stringa interpolata stessa. F# non converte in modo implicito una stringa interpolata in un oggetto FormattableString.

Sintassi estesa per l'interpolazione di stringhe

A partire da F# 8, quando si lavora con testo contenente già più {caratteri o } , % è possibile usare la sintassi di interpolazione di stringhe estesa per rimuovere la necessità di escape.

I valori letterali stringa tra virgolette triple possono iniziare con più $ caratteri, che cambiano il numero di parentesi graffe necessarie per aprire e chiudere l'interpolazione. In questi valori letterali stringa e { i caratteri non devono essere preceduti } da escape:

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

Il numero di caratteri necessari per gli identificatori di % formato è interessato nello stesso modo:

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

Interpolazione AOT nativa e con valori di stringa

Per formattare il testo senza un motore di formattazione basato su reflection, usare l'interpolazione con valori di stringa con buchi in formato normale o .NET:

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

F# 11 usa conversioni dirette e System.String.Concat per altre interpolazioni con valori di stringa. Un foro in formato .NET utilizza invarianti String.Format e riquadri il relativo argomento. Queste modifiche del compilatore supportano native AOT senza richiedere la compilazione core moderna; altro codice dell'applicazione può comunque richiedere la reflection.

I fori di tipo printf che richiedono la formattazione printf, ad esempio %04d{number} o %A{record}, possono comunque usare il percorso basato sulla reflection. I fori bare , %d%c, %i, e %M mantengono i controlli di tipo ed evitare la formattazione %sprintf. Altri identificatori, tra cui %u, non sono coperti da tale ottimizzazione. Un'interpolazione usata come PrintfFormat valore è distinta anche da una il cui tipo di risultato è string.

Compatibilità delle impostazioni cultura e del formato

I buchi semplici usano la conversione di string F#; .NET i fori in formato utilizzano la formattazione invariante. Per produrre output localizzato, selezionare le impostazioni cultura in modo esplicito:

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

Controllare l'output localizzato durante l'aggiornamento. FormattableString mantiene gli argomenti per la formattazione basata su provider successiva invece di seguire questo percorso di concatenazione.

Avviso FS3884 identifica una funzione non applicata o un delegato in un foro di interpolazione. Applicare la funzione se si intende il risultato:

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

Scrivere un valore nell'output standard

Per scrivere un valore senza un formato printf, FSharp.Core 11 aggiunge print e printn. Usano la string conversione; printn aggiunge una nuova riga:

print "Parcels: "
printn 3

Per l'output strutturale %A , usare la formattazione in testo non crittografato.

Registrare e unire l'output senza reflection

Con --reflectionfree, F# 11 può generare implementazioni significative ToString per record e unioni anziché visualizzare solo il nome del tipo:

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

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

Il progetto di esempio abilita il flag . L'output differisce da %A; i tipi di campo necessitano anche di implementazioni appropriate ToString .

Vedere anche