Minha jornada (até agora) com Elixir
Olá!
Depois de alguns artigos preparando terreno sobre concorrência, linguagens funcionais e temas relacionados, acredito que tenha chegado a hora de escrever com mais profundidade sobre Elixir.
Para saber o que é essa tal linguagem com nome de item do Final Fantasy, recomendo o seguinte vídeo:
Caso queira entender “de onde veio”, recomendo esse vídeo:
Caso você seja um pouco mais experiente e queira uma introdução hardcore, veja esse:
Se você quer só acompanhar o artigo, veja o primeiro. Se você quer de fato aprender algo, veja todos.
Continuando.
Eu tenho 10 anos de experiência em TI, a maior parte em C# — portanto, meu jeito de pensar é “orientado a objetos” — E depois de algumas semanas estudando Elixir a minha impressão foi a seguinte:
Alguns conceitos dentro do mundo OO podem ser absorvidos somente com palestras e apresentações teóricas. Eu estudei e ainda estudo muitos assuntos assim. Porém, descobri que para aprender um paradigma novo isso não funciona. Para absorver o novo paradigma, é preciso praticar.
E estou aqui para compartilhar o que funcionou comigo, espero que te ajude também :)
Uma técnica que eu uso para aprender algo novo é: além de ver os vídeos acima mencionados, procuro “cobrir terreno” de um determinado assunto e tento descobrir em termos quantitativos o que eu não sei sobre aquilo.
Para tais situações, recomendo diálogos budistas.
Você não leu errado não. E se eu te disser que podemos usar uma abordagem que utiliza algumas anedotas com plano de fundo técnico ao experimentar uma nova linguagem de programação?
Vamos conhecer os Koans de Elixir.
Durante as minhas pesquisas, descobri que é possível usar a mesma técnica para todas as principais linguagens usadas hoje.
Mas o que de fato são os Elixir Koans?
Nada mais é do que um conjunto de exercícios que você executa na sua máquina, separados por assunto e que utilizam da seguinte abordagem: tente fazer os testes de unidade corretamente usando as principais features da linguagem.
Ficou abstrato? Vamos a um passo a passo:
Após clonar o repositório do Koans, precisamos utilizar o Mix (que é o build tool padrão do Elixir). Pense no Mix como um equivalente ao npm/yarn do ecossistema Node.
O comando que restaura as dependências é o mix deps.get:
Todas as configurações relacionados ao Mix ficam contidas no arquivo mix.exs, na raiz do projeto. Dentro dele, é possível listar dependências, organizar o projeto por variáveis de ambiente e criar tarefas customizadas de build do projeto (conhecida como mix Tasks).
Minha impressão foi que as convenções usadas (relacionados a dependências, tasks e entry points) são bastante similares ao Node.
Após o restore do projeto, basta executar o comando mix meditate, que já irá exibir no terminal os exercícios:
O restante é experimentação, seguindo os erros apontados na linha da cor azul.
A lista de assuntos abordados pelos Koans é a seguinte:
Vou listar as principais impressões e diferenças que observei em comparação as linguagens que já usei na minha carreira (C#, JS, PHP, Python, Go e Java). Os exemplos foram feitos via a Repl do Elixir, chamada iex.
Comparadores: Achei bem padrão (usa ==, !=, >, <, igual a maioria das linguagens), existe o ===, mas é usado em cenários onde precisão é importante:
iex> 1 == 1.0
true
iex> 1 === 1.0
false
Strings: As strings em Elixir são representadas como um array de bytes em UTF-8, que podem ser convertidas para Codepoints (basicamente, caracteres representados por um único byte em Unicode) e Graphemes (caracteres com diacríticos, que são representados com 2 bytes):
iex> string = "\u0061\u0301"
"á"
iex> String.codepoints(string)
["a", "́"]
iex> String.graphemes(string)
["á"]
Numbers: Os módulos Integer e Float fazem as operações de conversão. Operações de arredondamento usam convenções comuns a outras linguagens (round, floor, ceil). Um detalhe que percebi é que não existe o operador de módulo mod (ou % em algumas linguagens), aqui se utiliza a função div para operações de divisão que retornam inteiros (o operador / sempre retorna floats) e função rem para a operação módulo (no qual o retorno é o resto da divisão):
iex> div(10, 2)
5
iex> div 10, 2
5
iex> rem 10, 3
1
Atoms: são constantes que seus nomes são seus próprios valores. Um ponto interessante que vale mencionar é que esse tipo na verdade é um inteiro mapeado para uma string (essa operação ocorre via Runtime pela BEAM) e é armazenado em uma atom table que tem um limite específico de 1048576 registros. Caso esse limite seja excedido, a BEAM morre. Além disso, o garbage collector não coleta atoms, logo, ficar gerando vários dinamicamente não é uma boa ideia. Há soluções para essa situação, no entanto. Mais detalhes sobre atoms aqui. São declarados com o caractere “:”. Em Elixir, booleanos também são atoms.
Exemplos:
iex> :apple
:apple
iex> :orange
:orange
iex> :apple == :apple
true
iex> :apple == :orange
false
iex> true == :true
true
iex> is_atom(false)
true
iex> is_boolean(:false)
true
Tuples: É um tipo chave valor composto de um atom como chave e um valor. O mais próximo que conheço em outras linguagens é o tipo KeyValuePair do C#. Um detalhe importante é que são armazenados de forma continua na memória e possuem índices, portanto, são rápidos:
iex> tuple = {:ok, "hello"}
{:ok, "hello"}
iex> elem(tuple, 1) #funcão que retorna o valor no indice 1 da tupla
"hello"
iex> tuple_size(tuple)
2
Lists: Achei bastante semelhante a outras linguagens — internamente, é uma lista ligada, portanto, fácil de ser manipulada — uma diferença de sintaxe que eu achei bastante agradável foi usar o operador ++ para adicionar itens da lista e -- para remover ao invés de funções como List.Add() ou List.Remove():
iex(5)> list = [0,2,4]
[0, 2, 4]
iex(6)> list ++ [9]
[0, 2, 4, 9]
iex(7)> list -- [2]
[0, 4]
Para não ficar muito extenso, vou parando por aqui (ainda faltam 14 tópicos dos Koans).
No próximo artigo, continuamos nossa jornada explorando Elixir.
Até!
Você gostou do conteúdo e gostaria de fazer mentoria comigo? Clique aqui e descubra como.