Primeiro código Erlang a funcionar
Eu lembro de ter feito algo assim em Prolog.
De fato, para alguém TÃO acostumado a programação procedural e a paradigmas “comuns”, é um tanto complicado começar a entender programação funcional. Eu, por exemplo, admito que a experiência anterior com Prolog me ajuda muito a conseguir pensar em Erlang.
Sim, Prolog é um paradigma diferente (programação lógica), mas a sintaxe do código que eu fiz, sinceramente, é praticamente Prolog. Vide:
-module(join_lists).
-export([join/2]).
join([Head|Tail], [Head2|Tail2]) -ᐳ
[Head|join(Tail, [Head2|Tail2])];
join([], [Head2|Tail2]) -ᐳ
[Head2|Tail2].
Qualquer pessoa que entenda Prolog consegue logo entender o código acima. A sintaxe é praticamente a mesma!
Mas, enfim, eu vou explicar linha a linha o que está sendo feito, para você também poder começar a entender:
-module(join_lists).
Toda linha que começa com “-” é uma instrução para o pré-compilador. Equivalente ao ’#’ do C/C++. Aqui estou declarando o nome do módulo. Não tenho certeza, mas acho que o nome do arquivo não influi no nome do módulo em si, ou seja, é pelo nome indicado aqui que seu módulo será chamado.
(Eu acho).
-export([join/2]).
Aqui eu digo que o módulo exporta essa função (“join/2” é exatamente como tratamos os predicados em Prolog). Eu poderia passar várias funções.
Ou seja: nos módulos Erlang, você tem que dizer explicitamente quais funções ele “publica” para o mundo exterior.
join([Head|Tail], [Head2|Tail2]) -ᐳ
[Head|join(Tail, [Head2|Tail2])];
Na prática isso é uma linha só. O que eu digo é o seguinte: “se for chamada a função “join” com dois argumentos, sendo eles duas listas “adequadas” (“proper lists”, não sei a tradução correta), retorne uma lista cujo primeiro elemento (head/cabeça da lista) é o head da primeira lista passada e o restante é o resultado de um “join” cujo primeiro argumento é o resto da primeira lista e o segundo argumento é a segunda lista em si”.
Essa “declaração” termina com ’;’ (ponto-e-vírgula), não ’.’ (ponto), pois é só uma parte da coisa toda.
join([], [Head2|Tail2]) -ᐳ
[Head2|Tail2].
Agora eu digo o seguinte: se for passado como primeiro argumento uma lista vazia (de onde não dá pra tirar um head, eis a diferença), o que deve ser retornado é a segunda lista, sem alterações.
Head? Tail?
Assim como em Prolog, toda lista em Erlang tem o formato [head|tail] ou [cabeça|resto]. O resto, por sua vez, pode tanto ser nada quanto outra lista, com o mesmo formato.
Assim, uma lista tipo [1,2,3,4] é, na verdade:
[1 | [2 | [3 | [4 | (NADA)]]]]
Sim, são como várias listas aninhadas! Mas, por questão de clareza, há o “atalho” que é “[1,2,3,4]”.
Este artigo foi escrito originalmente em 25/11/2014.