Conversão de Tipos
Passar um valor de um tipo para outro cai num destes três grupos, por ordem de risco:
| Grupo | Quando acontece | Como se escreve |
|---|---|---|
| Alargamento | Nenhuma informação se perde | Automático, não escreves nada |
| Cast | Pode perder informação, mas nunca falha | (tipo) valor |
| Conversão de texto | Pode falhar, porque o texto pode não ser um número | tipo::konverti(texto) |
Conversão implícita (widening)
Seção intitulada “Conversão implícita (widening)”O Kriol converte automaticamente valores numéricos quando a conversão é um alargamento seguro:
| De | Para | Automático |
|---|---|---|
bool | inteiro ou ponto flutuante | ✅ Sim |
| inteiro menor compatível | inteiro maior compatível | ✅ Sim |
| inteiro | ponto flutuante | ✅ Sim |
f32 | f64 / num | ✅ Sim |
int / i64 | num / f64 | ✅ Sim |
int x = 5;num y = x; // ok, alargamento automático int para num
fn aceita_num(num n) { mostran(n);}
fn inisiu() { aceita_num(10); // ok, int 10 é alargado para num}O caminho contrário nunca é automático. Estreitar um inteiro, ou passar de num para f32, exige um cast:
int grande = 200;u8 pequeno = grande; // ERRO: não se pode guardar um valor do tipo 'int' // na variável 'pequeno', que é do tipo 'u8'u8 certo = (u8) grande; // ok, pedido explicitamenteDe real para inteiro
Seção intitulada “De real para inteiro”Como em C, um valor real também se converte implicitamente num inteiro, truncando em direção a zero. Isto vale em declarações, atribuições, argumentos e retornos:
int a = 3.9; // 3int b = -3.9; // -3
fn metade(num x) int { divolvi x / 2; // o resultado real é truncado}Truncar não é arredondar: 3.9 dá 3 e -3.9 dá -3. Para arredondar valores positivos, soma meio antes de converter: (int) (x + 0.5).
Ao contrário do C, onde um valor fora do intervalo do tipo é comportamento indefinido, no Kriol fica no limite do tipo, e NaN dá 0.
Conversão explícita (cast)
Seção intitulada “Conversão explícita (cast)”As outras conversões que podem perder informação, como de um inteiro para um inteiro mais estreito, têm de ser pedidas explicitamente, escrevendo o tipo de destino entre parênteses antes do valor, como em C:
int a = (int) 3.9; // 3num b = (num) a / 2; // 1.5u8 c = (u8) 300; // 44bool d = (bool) 5; // sinO cast é um operador unário: liga mais forte do que os operadores binários, por isso (int) 3.9 + 1 é ((int) 3.9) + 1. Usa parênteses para converter uma expressão inteira: (int) (x + 1.5).
Um cast nunca falha e nunca para o programa, mas pode dar-te um valor que não querias, como no (u8) 300 acima.
O que cada conversão faz
Seção intitulada “O que cada conversão faz”| De | Para | Comportamento |
|---|---|---|
| real | inteiro | Trunca em direção a zero (-3.9 dá -3). Valores fora do intervalo ficam no limite do tipo (por exemplo (u8) 1000.5 dá 255) e NaN dá 0 |
| inteiro | inteiro mais estreito | Mantém os bits menos significativos ((u8) 300 dá 44, (i8) 200 dá -56) |
| inteiro | real | O valor mais próximo representável |
| real | outro real | Arredonda ao tipo de destino (f64 para f32) |
bool | número | sin dá 1 e nau dá 0 |
| número | bool | nau se for zero, sin caso contrário |
Repara na diferença entre as duas primeiras linhas: de real para inteiro o valor fica no limite do tipo, mas de inteiro para inteiro os bits que não caibam são descartados, e é por isso que (u8) 300 dá 44 e não 255.
O que não se pode converter
Seção intitulada “O que não se pode converter”Só números e bool são alvos válidos, e só números e bool se convertem. Estas conversões são erros de compilação:
int n = (int) "5"; // ERRO: não se converte textotextu t = (textu) 5; // ERRO: o destino não pode ser textuint m = (int) lista; // ERRO: não se converte um array ou um moldePara escrever um número como texto, usa uma f-string: textu t = f"{5}";.
Texto para número: T::konverti
Seção intitulada “Texto para número: T::konverti”Converter texto em número pode falhar (o texto pode não ser um número), por isso não é um cast. Usa tipo::konverti(texto), que usa o mecanismo de erros: falha com um Erru se o texto não for válido.
fn inisiu() : Erru { int idadi = tenta int::konverti("42"); num altura = num::konverti("1.75") sinon 0.0; mostran(f"{idadi}; {altura}"); // 42; 1.75}Funciona com todos os tipos numéricos (int, num, i8, u8, f32, …) e com bool:
| Tipo | Texto aceite |
|---|---|
| inteiros | Sinal opcional (+ ou -) e dígitos (42, -17). O valor tem de caber no tipo: u8::konverti("256") falha |
num, f32, f64 | Sinal opcional, dígitos, parte decimal opcional e expoente opcional (3.25, -2e3). 1. e nan são inválidos. O valor tem de caber no tipo: f32::konverti("1e300") falha |
bool | sin ou nau |
Os espaços no início e no fim do texto são ignorados. As mensagens de erro dizem o que correu mal, por exemplo 'abc' não é um número inteiro válido, '256' não cabe no tipo 'u8' ou 'x' não é um número válido. Um texto com mais de 40 bytes aparece cortado e termina em ....
Se o erro não for tratado com tenta ou sinon, o programa termina nessa chamada com a mensagem do erro. Ao contrário de uma função tua declarada com : Erru, o konverti não gera aviso de compilação quando o erro fica sem tratamento, nem com --strict.
Para converter um valor lido do utilizador, vê Ler números em Entrada de Dados.