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.