Mais um blog inútil.

Dezembro 11, 2010

Programação Funcional com Perl (parte I, revista e aumentada)

Filed under: Uncategorized — falco @ 22:23

Começo com este artigo uma série de artigos relacionados com a Programação Funcional com Perl.

Com estes artigos pretendo demonstrar algumas das capacidades do Perl para utilização com o paradigma de Programação Funcional. Não pretendo ensinar nem as bases da Programação Funcional, nem do Perl. Vou abrir excepções quando se tratarem de aspectos mais avançados e/ou muito relacionados com a própria Programação Funcional.
O objectivo destes artigos também não passa por colocar os leitores a fazer Programação Funcional pura, mas sim demonstrar as funcionalidades de Programação Funcional que o Perl dispõe.
Isto pode ser utilizado para praticar um estilo de programação com muitas semelhanças ao do paradigma da Programação Funcional, ou então simplesmente utilizar alguns "truques" para melhorar os programas que o leitor desenvolve.
A compreensão elementar do Perl e da Programação Funcional é um requisito para a compreensão destes artigos contudo tudo será explicado de forma a permitir que um principiante possa compreender tudo e quem tiver dúvidas poderá contactar-me para as esclarecer (falco @ Portugal a Programar).

Uma das principais características do Perl, em seguimento do mantra da sua comunidade («There's more than one way to do it»), é não obrigar o programador a utilizar. Nem escolher um paradigma de programação, mas sim permitir ao programador utilizar o que quiser, quando quiser. Fica ao cuidado dele ter os cuidados necessários para que o código seja útil e siga boas práticas de programação. Há quem concorde com esta filosofia, há quem não concorde, mas a filosofia do Perl e da sua comunidade não é o âmbito deste artigo.
Um dos muitos paradigmas de programação que são possíveis utilizar em Perl é a Programação Funcional. Contudo não cabe a este artigo explicar a Programção Funcional. Por isso sugiro que antes de prosseguirem na leitura deste artigo leiam pelo menos uma curta explicação do que é Programação Funcional (os primeiros parágrafos do artigo da Wikipedia sobre Programação Funcional por exemplo). Como já há vários artigos sobre Programação Funcional em diversas linguagem como Python, Scheme, Haskell (recomendo que os leiam), deixo aqui a sugestão a alguém, para redigir um artigo teórico e agnóstico (em relação a linguagens de programação) sobre Programação Funcional.

Algumas das funcionalidades elementares das linguagens funcionais são asfunções anónimas e as closures (mas não só). O Perl tem ambas as features e é por aí que vamos começar esta série de artigos.

Começamos pelas funções anónimas.
Quando declaramos uma função em Perl, a prática mais comum é atribuir-lhe um nome na sua declaração. As funções anónimas não têm esse nome. Por isso, quando as queremos invocar, temos que utilizar uma referência para essa função dita anónima.

Em Perl a declaração de funções anónimas é simples. Para declarar uma função utiliza-se uma outra função, a função sub e para declarar uma função anónima também.
Para criar uma função anónima invoca-se a função sub sem o parâmetro correspondente ao nome da função. E como retorno obtém-se um código de referência para a função declarada.

Uma das alterações que o Perl 5.12 trouxe foi uma função chamada say.
O say é basicamente um print que adiciona um newline à string que queremos imprimir (poupa-nos pelo menos 4 caracteres).

Qualquer uma das seguintes linhas de código vai imprimir isolado numa linha a string: «Hello world!»:

print "Hello world!\n";
print "Hello world!"."\n";
print "Hello world!", "\n";
say "Hello world!";

Para demonstrar a utilização de funções anónimas decidi criar uma implementação da função say, que antes da sua utilização permite definir como queremos que a string seja formatada:

sub say {   #definição da função say
    my ($string, $format) = @_;

    my $str = $format->($string);
    print $str;
}

my $format = sub {  #função anónima de formatação da string
        my $str = shift;
        return $str."\n";
    };

say("Hello world!", $format);

Explicação do código antecedente:

Primeiro é definida a função say, como definiríamos qualquer outra função em Perl.

Depois é definida a função anónima de formatação e atribui-se essa função a uma variável chamada format e que guarda uma referência para a função. A variável permite-nos ter uma forma de passar a função anónima para a função say.

Quais as utilidades das funções anónimas?

São diversas. E vão desde a modificação do comportamento de uma função, como no exemplo anterior, ou como nos mecânismos de callback, ou a criação de "dispach tables", como no exemplo que se segue:

my %lingua = (  #dispach table
        "pt" => sub { return "Olá mundo!" },
        "es" => sub { return "Hola mundo!" },
        "en" => sub { return "Hello world!" },
        "fr" => sub { return "Bonjour monde!" },
    );

sub dispach {
    my $l = shift;

    if(defined $lingua{$l} && exists $lingua{$l}) {
        my $str = $lingua{$l}->();
        print $str."\n";
    }
    else {
        print "Erro: lingua desconhecida!\n";
    }
}

dispach("fr");

Explicação do código antecedente:

Começou por ser definida uma hash table. Essa hash contém como chaves as opções válidas de línguas que queremos utilizar na impressão de uma saudação. E como valores, tem funções anónimas que imprimem uma saudação, na língua representada pela respectiva chave na hash table.

Em Perl há poderia ter sida implementada esta solução recorrendo a funções que não fossem anónimas. Mas isso traria imediatamente dois problemas: aumentaria a quantidade de código necessário e este artigo tem um limite de caracteres; não utilizaria funções anónimas, que é o objectivo deste exemplo ;). Para além de isso, o que é pretendido neste exemplo, é algo tremendamente simples que pode perfeitamente ser feito utilizando funções anónimas, sem se aumentar a dificuldade relevante da sua compreensão, quer como um todo, quer isoladamente.

A solução do exemplo, em vez de a utilização de um encadeamento maior de if-elsif, ou de um switch-case (também maior). Permite que a solução escale para mais opções de línguas, sem qualquer alteração e atinge melhor vários dos objectivos da utilização de funções na programação: conter/isolar os problemas de forma a simplificar a sua resolução, facilitar a compreensão do código.

No próximo, artigo vou falar da segunda das principais capacidades do Perl para a Programação Funcional de que falei antes, as closures.

(c) 2010 falco
Este artigo está licenciado de acordo com os termos da licença:
Atribuição - Uso Não-Comercial - Partilha nos Termos da Mesma Licença 2.5 que pode ser encontrada em: http://creativecommons.org/licenses/by-nc-sa/2.5/pt/legalcode
Em caso de dúvida, indisponibilidade de acesso à licença, ou se prentender algo que não seja permitido com esta licença, deverá contactar o autor no sentido de pedir exclarecimento, ou permissão para fazer o que pretende.

2 comentários a “Programação Funcional com Perl (parte I, revista e aumentada)”

  1. paf diz:

    adorava licenciar os meus artigos no blol.

  2. mirage diz:

    ffffffffffffffffuuuuuuuuuuuuuuuuuuuuuuuuuuu-

Comentar

widgeon
widgeon
widgeon
widgeon