ReasonML: Valores e Tipos básicos

O bê-a-bá em ReasonML

Esse artigo faz parte da série “O que é ReasonML?”.

Nesse artigo, analisaremos o suporte do ReasonML para booleanos, inteiros, pontos flutuantes, strings, caracteres e tipos de unidade. Também veremos alguns operadores em ação.

Para explorar, usaremos a linha de comando interativa do ReasonML, rtop, que faz parte do pacote reason-cli (veja no manual como instalá-lo).

1. Interações em rtop

Interações em rtop funcionam da seguinte maneira:

# !true;
- : bool = false

Duas observações:

  • Você deve terminar a expressão !true; com um ponto-e-vírgula para que seja avaliada.
  • rtop sempre imprime os tipos de resultados que ele calcula. Isso é especialmente útil mais tarde, com tipos mais complicados, ex: tipos de funções.

2. ReasonML é estaticamente tipado — o que isso significa?

Valores em ReasonML são estaticamente tipados. O que significa estaticamente tipados?

Por um lado, temos o termo tipo. Nesse contexto significa “conjunto de valores”. Por exemplo, bool é o nome do tipo de todos os valores booleanos: o conjunto (matemático) {false, true}.

Por outro lado, fazemos a seguinte distinção no contexto do ciclo de vida do código:

  • Estático: Em tempo de compilação, sem executar o código.
  • Dinâmico: em tempo de execução, enquanto o código está em execução.

Portanto, a digitação estática significa: ReasonML conhece os tipos de valores em tempo de compilação. E os tipos também são conhecidos ao editar o código, que suporta recursos de edição inteligentes.

Já encontramos um benefício da digitação estática: suporte de edição. Ela também ajuda a detectar alguns tipos de erros. E muitas vezes ajuda a documentar como funciona o código (de forma que seja automaticamente verificada quanto à consistência).

A fim de colher estes benefícios, você deve se acostumar a trabalhar com os tipos. Você obtém ajuda de duas maneiras:

  • ReasonML geralmente infere tipos (os escreve para você). Ou seja, um conhecimento passivo de tipos leva você surpreendentemente longe.
  • ReasonML mostra mensagens de erro descritivas quando algo dá errado, que podem até incluir dicas de como corrigir o problema. Ou seja, você pode usar o teste e o erro para aprender tipos.

O polimorfismo ad hoc pode parecer inteligente, mas tem uma definição simples e conseqüências práticas visíveis no ReasonML. Então tenha paciência.

O ReasonML atualmente não suporta polimorfismo ad hoc onde a mesma operação é implementada de forma diferente dependendo dos tipos de parâmetros. Haskell, outra linguagem de programação funcional suporta polimorfismo ad hoc através de classes de tipo. O ReasonML eventualmente pode suportá-lo através dos implícitos modulares.

O ReasonML não suporta polimorfismo ad hoc significa que a maioria dos operadores, como + (adição em inteiros), +. (adição em pontos flutuantes) e ++ (concatenação de string) apenas suportam um único tipo. Portanto, é sua responsabilidade converter operandos em tipos adequados. No lado positivo, o ReasonML irá avisá-lo no tempo de compilação se você esquecer de fazer isso. Isso é um benefício da tipagem estática.

3. Comentários

Antes de entrar em valores e tipos, vamos aprender comentários.

ReasonML só tem uma maneira de escrever comentários:

/* Isso é um comentário */

Convenientemente, é possível aninhar esse tipo de comentário (as linguagens com sintaxe em estilo C muitas vezes não são capazes de fazer isso):

/* Comentário de /* Comentário de dentro */ fora */

O aninhamento é útil para comentar peças de código:

/*
foo(); /* foo */
bar(); /* bar */
*/

4. Booleanos

Vamos digitar algumas expressões booleanas:

# true;
- : bool = true
# false;
- : bool = false
# !true;
- : bool = false
# true || false;
- : bool = true
# true && false;
- : bool = false

5. Números

Estas são expressões de números inteiros:

# 2 + 1;
- : int = 3
# 7 - 3;
- : int = 4
# 2 * 3;
- : int = 6
# 5 / 3;
- : int = 1

As expressões de ponto flutuante são as seguintes:

# 2.0 +. 1.0;
- : float = 3.
# 2. +. 1.;
- : float = 3.
# 2.25 +. 1.25;
- : float = 3.5
# 7. -. 3.;
- : float = 4.
# 2. *. 3.;
- : float = 6.
# 5. /. 3.;
- : float = 1.66666666666666674

6. Strings

Os literais para string normais são delimitados por aspas duplas:

# "abc";
- : string = "abc"
# String.length("ü");
- : int = 2
# "abc" ++ "def";
- : string = "abcdef"
# "Existem " ++ string_of_int(11 + 5) ++ " livros";
- : string = "Existem 16 livros"
# {| string literal
de múltipla linha
\ não escapa
|};
- : string = " string literal\nde múltipla linha\n\\ não escapa\n"

strings em ReasonML são codificadas como UTF-8 e não compatíveis com as strings UTF-16 do JavaScript. O suporte do ReasonML para Unicode também é pior do que o do JavaScript — que já é limitado. Como solução há curto prazo, você pode usar as strings JavaScript do BuckleScript em ReasonML:

Js.log("äöü"); /* não funciona */
Js.log({js|äöü|js}); /* äöü */

Essas seqüências de caracteres são produzidas através de literais de strings de múltiplas linhas, anotadas com js, que são tratadas exclusivamente pelo BuckleScript. No ReasonML nativo, você obtém strings normais.

7. Caracteres

Os caracteres são delimitados por citações simples. Somente os primeiros 7 bits do Unicode são suportados (sem umlauts etc.):

# 'x';
- : char = 'x'
# String.get("abc", 1);
- : char = 'b'
# "abc".[1];
- : char = 'b'

"x".[0] é açucar sintático para String.get("x", 0).

8. Tipos de unidade

Às vezes, você precisa de um valor denotando “nada”. O ReasonML tem o valor especial () para este propósito. () tem seu próprio tipo, unidade e é o único elemento desse tipo:

# ();
- : unit = ()

Em contraste com null em linguagens de estilo C, () não é um elemento de nenhum outro tipo.

Entre outras coisas, a unidade desse tipo é usada para funções com efeitos colaterais que não retornam nada. Por exemplo:

# print_string;
- : (string) => unit = <fun>

A função print_string leva uma string como um argumento e imprime essa string. Não tem resultado real.

9. Conversão entre tipos básicos

A biblioteca padrão do ReasonML possui funções para converter entre os tipos básicos:

# string_of_int(123);
- : string = "123"
# string_of_bool(true);
- : string = "true"

Todas as funções de conversão são denominadas da seguinte forma:

«outputType»_of_«inputType»

10. Mais operadores

A seguir, os operadores de comparação. Eles fazem parte dos poucos operadores que trabalham com vários tipos (eles são polimórficos).

# 3.0 < 4.0;
- : bool = true
# 3 < 4;
- : bool = true
# 3 <= 4;
- : bool = true

No entanto, você não pode misturar os tipos de operandos:

# 3.0 < 4;
Error: Expression has type int but expected type float

ReasonML possui dois operadores de igualdade.

O duplo igual (igualdade por valor) compara valores e faz isso mesmo para tipos de referência, como listas.

# [1,2,3] == [1,2,3];
- : bool = true

Em contraste, o triplo igual (igualdade por referência) comparam as referências:

# [1,2,3] === [1,2,3];
- : bool = false

== é o operador de igualdade preferido (a menos que você realmente deseja comparar referências).

Créditos

Written by

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store