Fenner
A linguagem

Interpolação de cadeias e formatos

$'Olá, {LName}!' com expressões e formatos {x:8:2}, {x:x4}, {x:n2}, enum pelo nome e datas.

O que é e por que existe#

Montar uma linha de texto com + e IntToUStr é verboso e fácil de errar. A cadeia interpolada põe a expressão dentro do texto, e cada valor é convertido pelo tipo:

Fenner
WriteLn($'Olá, {LName}! Você tem {LQty} itens e {LQty * 2} no dobro.');

O $ vem colado no apóstrofo. Dentro das chaves vai qualquer expressão; espaços em volta são livres.

EscritoSignifica
$'texto'abre a cadeia interpolada
{expr}qualquer expressão
{{ e }}chaves literais (uma } solta é erro)
''apóstrofo literal, como no literal comum

Dentro de {…} os apóstrofos abrem texto (e as chaves dele não contam) e uma interpolada pode conter outra. O resultado é UString.

Como cada tipo é convertido#

TipoConversão
inteirosIntToUStr / UIntToUStr
Float16…Float128com ponto decimal (7.5)
Currency*com ponto decimal
Bool8…Bool64texto do BoolToUStr (a RTL devolve sim/não)
AChar, WCharcadeia de 1 caractere
cadeiascomo estão
enumeradoo nome do membro
classe com function ToString: <cadeia> sem parâmetroschamada virtual a ToString

Formatos: {expr:formato}#

FormatoSignifica
W e -Wa conversão normal em W colunas (à direita; - à esquerda)
W:Dponto fixo com D casas em W colunas (real e moeda), como o x:8:2 do Pascal
d[P], x[P], X[P]inteiro decimal, hexa minúsculo, hexa maiúsculo; P é o mínimo de dígitos
f[P], e[P], n[P]ponto fixo, científico, com vírgula de milhar (padrão 2 casas em f e n)
g[P]geral: o mais curto entre fixo e científico (P algarismos significativos, padrão 6)
letra + :Wcombina, como em f3:10 ou X8:-12
data/horaexpressão real (Float64, TJulianDateTime) com um formato do FormatDateTime (yyyy-mm-dd hh:nn); exige uses System.Remainder

O : só é especificador no nível 0 da expressão (fora de parênteses, colchetes, chaves e apóstrofos). Por isso um ternário vai entre parênteses: {(LQty > 40 ? 'muitos' : 'poucos')}. Decimal é sempre ponto e milhar sempre vírgula.

rc-interp.fxp
program InterpolacaoSaida;
// Demo 13 - Saída no console e interpolação de texto: $'...{expressão:formato}...'.
// Não há entrada interativa: aqui só mostramos como formatar o que sai.

type
  TColor = (Red, Green, Blue);

var
  LQty: Int32;
  LPrice: Float64;
  LName: UString;
  LColor: TColor;
begin
  LQty := 42;
  LPrice := 1234.5678;
  LName := 'Ana';
  LColor := TColor.Green;

  // Write não pula linha; WriteLn pula. Aceitam vários argumentos de tipos diferentes.
  Write('Sem pular, ');
  Write('e agora pulando: ', LQty, ' ', LPrice);
  WriteLn;

  // Formato clássico de Pascal: valor:largura:decimais.
  WriteLn('[', LQty:6, ']  [', LQty:-6, ']  [', LPrice:10:2, ']');

  // Interpolação: o texto entre {chaves} é uma expressão qualquer.
  WriteLn($'Olá, {LName}! Você tem {LQty} itens e {LQty * 2} no dobro.');

  // Formatos depois de ":" dentro das chaves.
  WriteLn($'largura 8      : [{LQty:8}]');
  WriteLn($'alinha esquerda: [{LQty:-8}]');
  WriteLn($'com zeros (d5) : [{LQty:d5}]');
  WriteLn($'hexa           : {LQty:x} {LQty:X4} {LQty:x4}');
  WriteLn($'real f2        : {LPrice:f2}');
  WriteLn($'largura:casas  : [{LPrice:10:1}]');
  WriteLn($'milhar n2      : {LPrice * 1000:n2}');
  WriteLn($'científico e3  : {LPrice:e3}');
  WriteLn($'enumerado      : {LColor}');

  // Para escrever uma chave literal, duplique-a.
  WriteLn($'chaves literais: {{LName}} = {LName}');

  // Dá para usar condicional dentro (entre parênteses) e chamar funções.
  WriteLn($'situação: {(LQty > 40 ? 'muitos' : 'poucos')}, maiúsculo: {UStrUpper(LName)}');
end.
Saída
Sem pular, e agora pulando: 42 1234.57
[    42]  [42    ]  [   1234.57]
Olá, Ana! Você tem 42 itens e 84 no dobro.
largura 8      : [      42]
alinha esquerda: [42      ]
com zeros (d5) : [00042]
hexa           : 2a 002A 002a
real f2        : 1234.57
largura:casas  : [    1234.6]
milhar n2      : 1,234,567.80
científico e3  : 1.235e+03
enumerado      : Green
chaves literais: {LName} = Ana
situação: muitos, maiúsculo: ANA

Demo 13. Os formatos de largura, esquerda, d5, hexa, f2, largura:casas, n2, e3, enum e chaves literais.

Uma forma de várias linhas abre com $''' seguido de fim de linha e fecha com ''' sozinho numa linha; o recuo do fecho é retirado.

Armadilhas e erros típicos#

  • Em const: a interpolada sem expressão vale (const T = $'x {{y}}';); com expressão dentro é erro FE0254 ("numa constante só cabe texto sem expressões").
  • Tipos sem conversão: record, vetor, ponteiro e classe sem ToString não convertem.
  • Arredondamento é o do UStrFmt: 1.25:f1 não vira necessariamente 1.3. Confira o caso que lhe interessa.
  • Sem localidade: não há milhar nem decimal conforme o idioma do sistema.
  • Dentro das chaves, o fc --symbols não gera referência a identificadores da interpolada (vale para "ir para a definição" no editor).
  • LString não se mistura com UString na mesma interpolada (a mesma queixa do +).

Veja também#

  • Léxico e Tipos, para as cadeias.
  • Demos 13-interpolacao-saida e 55-conforto.