Literais


Toda linguagem de programação tem valores literais para codificar valores de certos tipos. No Pony você pode expressar booleanos, tipos numéricos, caracteres, strings e arrays como literais.

Literais Bool

Há o verdadeiro, tambem há o falso. Apenas isto.

Literais numéricos

Os literais numéricos podem ser usados para codificar qualquer número inteiro ou de ponto flutuante assinado ou não assinado. Na maioria dos casos, Pony é capaz de inferir o tipo concreto do literal a partir do contexto onde ele é usado (por exemplo, atribuição a um campo ou variável local ou como argumento para um método/chamada de comportamento).

É possível ajudar o compilador a determinar o tipo de concreto do literal usando um construtor de um dos tipos numéricos:

  • U8, U16, U32, U64, U128, USize, ULong
  • I8, I16, I32, I64, I128, ISize, ILong
  • F32, F64
let my_explicit_unsigned: U32 = 42_000
let my_constructor_unsigned = U8(1)
let my_constructor_float = F64(1.234)

As letras inteiras podem ser dadas como decimais, hexadecimais ou binários:

let my_decimal_int: I32 = 1024
let my_hexadecimal_int: I32 = 0x400
let my_binary_int: I32 = 0b10000000000

As literais de ponto flutuante são expressas como ponto flutuante padrão ou notação científica:

let my_double_precision_float: F64 = 0.009999999776482582092285156250
let my_scientific_float: F32 = 42.12e-4

Literais de Caracteres

Os caracteres literais são delimitados com aspas simples (').

Os caracteres literais, ao contrário dos literais de string, codificam para um único valor numérico. Normalmente, este é um byte único, um U8. Mas eles podem ser coagidos a qualquer tipo de inteiro:

let big_a: U8 = 'A' // 65
let hex_escaped_big_a: U8 = '\x41' // 65
let newline: U32 = '\n' // 10

As seguintes sequências de fuga são suportadas:

  • \x4F sequência de fuga hexagonal com 2 dígitos hexagonais (até 0xFF)
  • \a, b, e, f, f, n, r, r, t, v, 0, 0, 0, 0

Caracteres multibyte literais

É possível ter caracteres literais que contenham vários caracteres. O valor inteiro resultante é construído byte por byte com cada caractere representando um único byte no inteiro resultante, sendo o último caractere o byte menos significativo:


let multiByte: U64 = 'ABCD' // 0x4142434

Literais de Strings

Os caracteres literais das strings são delimitados com aspas duplas " ou com aspas triplas """. Eles podem conter qualquer tipo de bytes e várias sequências de fuga:

  • \u00FE Sequência de fuga unicode com 4 dígitos hexadecimais codificando um ponto de código
  • \u10FFFE Sequência de fuga unicode com 6 dígitos hexadecimais codificando um ponto de código
  • \x4F sequência de escape hexadecimal para letras unicode com 2 dígitos hexadecimais (até 0xFF)
  • \a, b, e, f, f, n, r, r, t, v, 0, 0, 0, 0, 0".

Cada sequência de fuga codifica um caractere completo, não um byte. use "format"


actor Main
new create(env: Env) =>
let pony = "🐎"
let pony_hex_escaped = "p\xF6n\xFF"
let pony_unicode_escape = "\U01F40E"
env.out.print(pony + " " + pony_hex_escaped + " " + pony_unicode_escape)
for b in pony.values() do
env.out.print(Format.int[U8](b, FormatHex))
end

Todas as strings suportam literalmente strings de várias linhas:

let stacked_ponies = "
🐎
🐎
🐎 "

Literais de Strings e Codificações

Os literais das strings contêm os bytes que foram lidos de seu arquivo de código fonte. Seu valor real, portanto, depende da codificação de sua fonte.

Considere o seguinte exemplo:

let u_umlaut = "ü"

Se o arquivo contendo este código for codificado como UTF-8, o byte-valor de u_umlaut será: \{xc3}xbc. Se o arquivo for codificado com ISO-8559-1 (Latin-1), seu valor será \xfc.

Strings triplamente citadas

Para a incorporação de texto com várias linhas em caracteres literais, existem três cadeias de caracteres citadas.

let triple_quoted_string_docs = """

Strings entre aspas triplas são a melhor opção para textos longos com várias linhas. Eles são amplamente usados ​​como docstrings que são transformados em documentação de API.

Eles recebem algum tratamento especial, a fim de manter o código Pony legível:

  • O literal de string começa na linha após a aspa tripla de abertura.
  • Indentação comum é removida do literal de string para que possa ser convenientemente alinhado com a indentação envolvente por exemplo. cada linha deste literal terá seus primeiros dois espaços em branco removidos.
  • Os espaços em branco após a abertura e antes da cotação tripla de fechamento serão removido também. A primeira linha será completamente removida se apenas contém espaços em branco. por exemplo. este primeiro caractere da string é `T` e não` \ n`.

Instâncias Literárias de Strings

Quando uma única string literal é usada várias vezes em seu programa Pony, todas elas serão convertidas em uma única instância comum. Isto significa que eles serão sempre iguais com base na identidade.

let pony = "🐎"
let another_pony = "🐎"
if pony is another_pony then
// True, therefore this line will run.
End

Literais da matriz

As letras das colunas estão entre parênteses rectos. Os elementos literais da matriz podem ser qualquer tipo de expressão. Eles são separados por ponto-e-vírgula ou nova linha:

let my_literal_array =
[
"first"; "second"
"third one on a new line"
]

Tipo de inferência

Se o tipo da matriz não for especificado, o tipo resultante da expressão literal da matriz é Array[T] ref onde T (o tipo dos elementos) é inferido como a união de todos os tipos de elementos.

let my_heterogenous_array =
[
U64(42)
"42"
U64.min_value()
]

No exemplo acima, o tipo de matriz resultante será Array[(U64|String)] ref, porque a matriz contém elementos String e U64. Se a variável ou argumento de chamada à qual o array literal é atribuído tem um tipo, o literal é coagido a esse tipo:

let my_stringable_array: Array[Stringable] ref =
[
U64(0xA)
"0xA"
]

Aqui my_stringable_array é coagida a Array[Stringable] ref. Isto funciona porque Stringable é uma característica que tanto String como U64 implementam.

Também é possível retornar uma array com uma Capacidade de Referência diferente da ref. apenas especificando-a no tipo:

let my_immutable_array: Array[Stringable] val =
[
U64(0xBEEF)
"0xBEEF"
]

Desta forma, as matrizes literais podem ser usadas para criar matrizes de qualquer Capacidade de Referência.

Como Expressão

Também é possível dar uma dica literal sobre que tipo de tipo deve coagir os elementos da matriz a usar um como Expressão. A expressão com o tipo de elemento de matriz desejado precisa ser adicionada logo após a abertura do colchete, delimitada por dois pontos:

let my_as_array =
[ as Stringable:
U64(0xFFEF)
"0xFFEF"
U64(1 + 1)
]

Esta matriz literal é coagida a ser uma ref. Array[Stringable], de acordo com a expressão. Se um tipo for especificado no lado esquerdo, ele precisa corresponder exatamente ao tipo na forma de expressão.

Matrizes e Referências

A construção de uma matriz com um literal cria novas referências a seus elementos. Assim, para ser 100% tecnicamente correto, os elementos literais de array são inferidos como sendo o alias do tipo de elemento real. Se todos os elementos forem do tipo T, o array literal será inferido como Array[T!] ref, ou seja, como um array de alias do tipo T.

Portanto, é necessário usar elementos que podem ter mais de uma referência do mesmo tipo (por exemplo, tipos com val ou ref) ou usar tipos efêmeros para outras capacidades (como retornado dos construtores ou a expressão de consumo).