quarta-feira, 18 de junho de 2008

Erlang é dificil?

Erlang é realmente dificil?

-module(tut).
-export([generate/1]).

%%
%% Funcao generate(X)
%% Quando X for 0, retorna [0]
%% Quando X > 0, retorna [X,X-1,...,0]
%% Caso contrario retorna [0,1,2,...,abs(X)]
%%
generate(0) -> [0];
generate(L) when integer(L) -> gera_lista(L).

gera_lista(L) when L > 0 -> gera_lista_direita(L);
gera_lista(L) -> gera_lista_inversa(-L).

gera_lista_direita(L) -> gera_lista_direita(L,[]).

gera_lista_direita(-1,Z) -> Z;
gera_lista_direita( L,Z) ->
%io:format("chamando: gera_lista_direita(~p,Z)~n",[L]),
gera_lista_direita(L - 1,[L | Z]).

gera_lista_inversa(L) -> gera_lista_inversa(L,[]).

gera_lista_inversa(-1,Z) -> Z;
gera_lista_inversa( L,Z) -> gera_lista_inversa(L,0,Z).

gera_lista_inversa(-1,_,Z) -> gera_lista_inversa(-1,Z);
gera_lista_inversa( L,A,Z) ->
%io:format("chamando: h(~p,~p,Z)~n",[L,A]),
h(L - 1, A + 1,[A | Z]).


Ok, dessa forma é dificil. Erlang é uma linguagem funcional, ou seja, suas funções seguem um raciocínio matemático e não imperativo. Vc sente o problema quando quer resolver algo iterativo ou utilizar variaveis de qualquer forma.

Fiz uma pequena função chamada generate, do modulo tut (de tutorial, uma vez que estou seguindo um). Ela é muito simples, se vc informar 0, ela gera uma lista simples contendo 0. Se vc passar um numero positivo ela gera uma lista de 0 até o número, inclusive. Se o numero for negativo, ele assume que vc quer fazer fazer a lista de forma inversa.

Veja só:
$ erlc tut.erl   # compilando o modulo
$ erl
Erlang (BEAM) emulator version 5.5.5 [source] [async-threads:0] [kernel-poll:false]

Eshell V5.5.5 (abort with ^G)
1> c(tut). # carregando o modulo
{ok,tut}
2> tut:generate(0). # invocando modulo:funcao(parametros).
[0]
3> tut:generate(10).
[0,1,2,3,4,5,6,7,8,9,10]
4> tut:generate(-10).
[10,9,8,7,6,5,4,3,2,1,0]
5>


A função generate chama a função gera_lista se o parametro passado for um número inteiro.
A função gera_lista chama a função para gerar a lista direita ou inversa, de acordo com o valor do parâmetro.

Veja só a simplicidade:

gera_lista_direita(L) -> gera_lista_direita(L,[]).

gera_lista_direita(-1,Z) -> Z;
gera_lista_direita( L,Z) ->
%io:format("chamando: gera_lista_direita(~p,Z)~n",[L]),
gera_lista_direita(L - 1,[L | Z]).


quando eu chamo gera_lista_direita(10) eu estou, na verdade, chamado a função gera_lista_direita(10,[]), onde eu fico usando uma lista como acumulador.

A operação [L | X] pode ser lida como [ elemento | lista ] , ou seja, eu adiciono um elemento em uma lista. gera_lista_direita(10,[]) vai chamar, então, gera_lista_direita(9,[10]), e depois gera_lista_direita(8,[9, 10]), e assim recursivamente até gera_lista_direita(-1,Z), quando eu retorno a lista. Fica claro se removerem os comentários (%) da frente dos io:format, que é a forma de fazer PPADD (Passei Por Aqui Driven Development) em Erlang.

Erlang precisa de MUITA pratica, principalmente de quem nunca programou em uma linguagem funcional e fica tentado a fazer coisas 'não ortodoxas' ;-)

Ah sim, o google é seu amigo:

http://www.dei.isep.ipp.pt/~paf/orgcdocs/Intro_Erlang.pdf

5 comentários:

Guilherme Garnier disse...

Legal Pac. Mas vc não explicou como fazer BDD com Erlang no Giraffas...

Tiago Peczenyj disse...

Uma coisa de cada vez.

Só depois eu descobri que erlang ja tem todas essas funções no módulo lists -- e deve ser até bem mais rápido.

Erlante tem um framework eunit, mas ai fazer BDD com isso são outros 500.

Tiago Albineli Motta disse...

Mas o negócio não é só fazer BDD com Erlang, é fazer BDD com Erlang no Giraffas! Aí sim o bicho pega. Só conheço uma pessoa no mundo capaz de fazer isso.

Tiago Peczenyj disse...

Exatamente. Mas eu bloguei primeiro }-)

anselmo alves disse...

Para os que quiserem mais informações sobre BDD com Erlang no Giraffas ou até desmistificar o tema, acessem: 2web.