Primeiras impressões com Elixir

Como consta no próprio site, Elixir é uma linguagem dinâmica e funcional, desenhada para construir aplicações escaláveis e de fácil manutenção. Ela foi criada pelo brasileiro José Valim que, insatisfeito com algumas coisas em Ruby, linguagem que utilizava em sua empresa, Plataformatec, pesquisou uma forma mais elegante de resolver certos problemas. Ele, então, começou a estudar Erlang (uma senhora linguagem, que roda no WhatsApp, como falei neste post), e resolveu criar o Elixir, que roda sobre a máquina virtual do Erlang (BEAM), com uma sintaxe mais “ruby-like”. Porém, para quem vem de uma linguagem com sintaxe estilo C, e seguindo os paradigmas procedural e orientado a objeto, o Elixir pode parecer estranho. Mas não se engane, por trás da sintaxe diferente, e de outra forma de pensar, existe uma linguagem poderosa, que tem ganhado bastante adeptos.

Meu primeiro contato com linguagens funcionais foi no meu primeiro ano na Engenharia de Computação (que posteriormente trocaria para Sistemas de Computação), com Scheme (uma linguagem baseada no Lisp), o que me permitiu ter uma adaptação um pouco mais fácil ao Elixir – por exemplo, na questão do head | tail, que usei nas aulas para fazer recursões (algo como “enquanto existir tail, remova o tail e some ao resultado). Neste começo de aprendizado, estou utilizando o livro Programming Elixire lendo alguns blogs sobre a linguagem, como os posts do Fábio Akita em seu site, o Akita on Rails.

Duas coisas chamam a atenção logo de cara: o operador = (igual) e o fato de todo tipo de dado ser imutável. Neste tópico (que começo a pensar em fazer uma série, pois este texto já está bem grande, e ainda nem colocamos código), vamos abordar essas duas características.

1) O operador =

Na maioria das linguagens, o operador = é de atribuição. Isso significa que sua função é unicamente atribuir o que estiver do seu lado direito, para o que está na esquerda. Isto é, x = 3 atribui o valor 3 à variável x. y = x + 3, fará com que seja realizada a operação do lado direito, para posteriormente ser armazenada na variável y. Em Elixir (e isto soa estranho, será que o correto é “No Elixir”?), não é bem assim.

O operador = é um match operator (e eu não sei qual a tradução para isso). Com isso, sua função é mais do que apenas atribuir valores. Para entender melhor, vamos recorrer a documentação da linguagem, que traz o seguinte exemplo:

Match Operator Elixir
Match Operator Elixir

 Como percebe-se pela imagem, além da função de atribuir 1 a x, este operador também avalia a expressão. Depois de atribuir 2 a x, está correto inverter os termos, dizendo que 2 é igual a x. Porém, ao tentar comparar qualquer outro valor a x, ocorre um erro, já que x não corresponde a 3, mas sim a 2. (É um pouco confuso, eu sei. Talvez eu mesmo não tenha entendido ou conseguido explicar direito).

Além disso, é perfeitamente válido o código a seguir:

O operador = é bastante poderoso em Elixir
O operador = é bastante poderoso em Elixir

Acho que deu para entender o funcionamento básico do =. Passemos, então, ao próximo item da lista: a imutabilidade dos dados em Elixir.

2) Imutabilidade dados

Uma das motivações que resultaram no desenvolvimento do Elixir foi o fato de que a mutabilidade dos dados (ie, sua capacidade de alterar seu próprio conteúdo) nem sempre é algo benéfico, pois torna mais difícil entender onde o dado foi mudado (principalmente quando estivermos chamando diversas funções).

Para entender direito como funciona essa questão, recorri ao StackOverflow. Deu para entender melhor como funciona: ao contrário de linguagens imperativas, nos quais as variáveis são espaços (alocados) para valores, em Elixir/Erlang, variáveis são simplesmente labels, ou etiquetas, que ligam o nome a um determinado valor.

Uma diferença grande o Elixir e Erlang é que o primeiro permite “remapear” a variável, isto é, fazê-la apontá-la para outro valor (desde que explicitamente, já falaremos sobre). Em Erlang, isso não é possível. Uma vez que determinado label tenha sido atribuído, ele não poderá ser modificado.

Na primeira imagem, por exemplo, primeiro fiz com que x apontasse para o valor 1, e posteriormente modifiquei, fazendo com que apontasse para 2 (embora eu esteja em dúvida se a nomenclatura esteja correta, vocês entenderam o ponto).

Todavia, a parte divertida fica com isso:

data_immutable

No começo deste código, estou definindo uma tupla (um dos tipos básicos da linguagem), com duas posições (olá e visitante). Após, estou usando a função put_elem, que recebe três parâmetros, a tupla original, o indíce (que começa em 0, tal qual C), e o novo valor desta posição.

Mas repare que o retorno da função é {“olá, “leitor”}, mas quando imprimimos teste, o valor ainda é visitante (valor original). Por quê? Porque as estruturas são imutáveis, como falei. Mas repare que, embaixo, estou atribuindo teste a esta nova tupla. Isso anula a imutabilidade? Não, porque, como falei, o nome é apenas uma etiqueta, que foi posta nesta nova tupla.

Bom, acho que por enquanto está bom. Pretendo escrever mais sobre essa linguagem, que achei bem interessante. No próximo texto, falarei um pouco mais da sintaxe – como o que é uma tupla, que não ficou muito claro no exemplo acima.