Depuração de scripts Perl

janeiro 26, 2009 by

Sabe-se que em Perl os warnings nem sempre são esclarecedores. Ao contrário, o que era fácil, fica críptico.

Pegando leve, vamos ver um exemplo:

use strict;
use warnings;
my %hash = {
  cachorro => 'mamífero',
  golfinho => 'mamífero',
  tartaruga => 'réptil',
  galinha => 'galináceo'
}

E é claro que isso vai dar um erro grotesco:

Reference found where even-sized list expected at hasht.pl line 5.  (WTF!??)

Pra resolver a questão de vez, adicione o pacote diagnostics, ficando assim:

use warnings;
use strict;
use diagnostics;
my %hash = {
  cachorro => 'mamífero',
  golfinho => 'mamífero',
  tartaruga => 'réptil',
  galinha => 'galináceo'
}

Magicamente, o Perl praticamente nos dá uma aula junto com o erro:

Reference found where even-sized list expected at hasht.pl line 5 (#1)
(W misc) You gave a single reference where Perl was expecting a list
with an even number of elements (for assignment to a hash). This
usually means that you used the anon hash constructor when you meant
to use parens. In any case, a hash requires key/value pairs.

%hash = { one => 1, two => 2, };        # WRONG
%hash = [ qw/ an anon array / ];        # WRONG
%hash = ( one => 1, two => 2, );        # right
%hash = qw( one 1 two 2 );              # also fine

Ou seja, era só trocar as chaves por parênteses. Agora ficou mole, ou pelo menos bem mais fácil de entender as mensagens esquisitas dessa linguagem fabulosa!

Array, Hash, Referência de Array, Referência de Hash

janeiro 21, 2009 by

Serei breve. Resumão de como e quando acessar array, hash, referência de array e referência de hash.

pai_mei
Continue lendo »

Trandução da documentação Perl para Português

janeiro 14, 2009 by

No site oficial do Perl Brasil existe um projeto de tradução da documentação do Perl para o português.

Quem puder contribuir…
Fará com que o Perl se torne mais acessível no Brasil.

segue o link: http://www.perl.org.br/Perldoc/WebTranslation

Calendários do Advento Natalino

dezembro 4, 2008 by

Replico aqui um post interessante do Breno na lista de Perl do Rio de Janeiro sobre recomendações de módulos de no mês de dezembro.

Acompanhem!
http://perladvent.pm.org/2008/

———- Forwarded message ———-
From: breno
Date: 2008/12/4
Subject: [Rio-pm] Calendários do Advento Natalino!
To: Perl Mongers Rio de Janeiro

O calendário Perl do advento natalino é uma tradição na comunidade desde o ano 2000. A idéia é apresentar um módulo bacana (para qualquer definição de “bacana”) do CPAN em cada dia de dezembro que antecede o Natal.

O desse ano já está no ar!

http://perladvent.pm.org/2008/

O dia 1 fala do ToolSet, um módulo que agrega todos os seus módulos mais usados em um único import, evitando assim o “ctrl-c/ctrl-v”.

Dia 2 fala de um módulo que eu particularmente acho o maior barato, o Math::Prime::TiedArray, que cria um array virtual com todos os números primos.Todos?! Todos. Afinal, é um array virtual, ele computa o número primo que ocupa a posição desejada conforme a demanda 😉

Fiquem atentos ao site oficial do calendário! Quem tiver curiosidade é só olhar o histórico para os outros anos, e se vc acha que seu [insira módulo xodó aqui] está sendo injustiçado por não ter sido apresentado
até hoje, escreva para eles! O pessoal do calendário está sempre atrás de idéias (e escritores!!!!!)

Finalmente, mas não menos importante, já saiu também o calendário Catalyst do advento natalino, que desde 2005 complementa o calendário do Perl com dicas e módulos específicos para o Catalyst!

http://www.catalystframework.org/calendar/2008/

O dia 1 apresenta as estatísticas da pesquisa de Catalyst (que circulou inclusive pela lista, infelizmente apenas 2 brasileiros responderam).

Dia 2 mostra as diferentes formas de se implantar o Catalyst em servidores Web (servidor built-in, mod_perl, fastcgi, etc)

O dia 3 apresenta um módulo bonitão que já mencionei por aqui, o Chart::Clicker, e como usá-lo junto com o Catalyst para exibir páginas com gráficos informativos.

Como sempre, é possível ver calendários de anos anteriores, e eles também adoram voluntários!

[]s, e boas festas 😉

-b
_______________________________________________
Rio-pm mailing list
Rio-pm@pm.org
http://mail.pm.org/mailman/listinfo/rio-pm

Template Toolkit no Perl

dezembro 3, 2008 by

Acho que uma das poucas coisas que gosto no Perl é o módulo Template Toolkit. Como a documentação é boa, vou só dar uma olhada superficial.

Comecemos pela instalação:

# aptitude install libtemplate-perl

O uso é semelhante a qualquer biblioteca de templates, como o Smarty no PHP. Preparamos as variáveis que serão disponibilizadas e em seguida processamos determinado arquivo.

O script fica assim:

use strict;
use warnings;
 
use Template;
use File::Basename;
 
my $r = shift;
$r->content_type("text/html");
 
my $directory = (fileparse $r->filename)[1];
 
my $template = Template->new({
    INCLUDE_PATH => "$directory/templates",
});
 
my $vars = {
    artista => 'Pink Floyd',
    album   => 'Pulse',
    musicas => [
        { numero => 12, titulo => 'Comfortably Numb' },
        { numero => 11, titulo => 'Wish You Were Here' },
        { numero => 3,  titulo => 'Time' },
    ],
};
 
$template->process('musica.tt2', $vars)
    || die $template->error();

E o template:

<html>
<body>
    <h1>[% artista %]</h1>
    <h2>[% album %]</h2>
    [% IF musicas %]
        <ul>
        [% FOREACH musica IN musicas %]
            <li>[% musica.numero %] – [% musica.titulo %]</li>
        [% END %]
        </ul>
    [% ELSE %]
        <p>Nenhuma música.</p>
    [% END %]
</body>
</html>

Quem já está acostumado a utilizar templates vai precisar apenas se adaptar à sintaxe do Template Toolkit.

Em relação ao script, o trecho my $directory = (fileparse $r->filename)[1]; é uma peculiaridade do mod_perl. O diretório atual do processo não é o diretório do script, aqui ficou como sendo a raiz do sistema. Então se tentássemos carregar o template templates/musica.tt2 ele não encontraria o arquivo.

A função fileparse do módulo File::Basename retorna uma lista com o nome do arquivo, diretório e sufixo, respectivamente. Da forma como foi utilizada, o diretório do arquivo que está sendo processado é atribuído à variável $directory. Essa variável então é utilizada como base para o caminho absoluto do diretório dos templates que é passado como configuração para o Template Toolkit.

Também é importante verificar se o template foi processado corretamente. Se não houvesse a linha || die $template->error(); e o processamento do template desse erro, a função process apenas retornaria 0, sem mostrar nada na tela. Utilizando o die como demonstrado, qualquer problema vai mostrar Internal Server Error no browser e detalhes do erro no error.log do Apache.

Recomendo a leitura

Hashings de perl

dezembro 1, 2008 by

São os array associativos.
As variáveis hashings são precedidas de %.

%idade = ();  # Cria uma hashing vazio.
%idade = ('jabuti', 80, 'rato', 3, 'cobra', 6);
# Outra maneira de fazer o mesmo acima.
%idade = (tuatara => 35, cachorro => 12, harpia => 40);
%idade{elefante} = 70;

Usando o operador => não é necessário usar aspas, no item a direita

Para acessar os dados de um hashing devemos usar o { e } para indicar o índice e $ precedendo a variável.

$idade_animal = $idade{jabuti};

Podemos acessar os índices dos hashings usando a função key.

# @animais agora é ('harpia', 'tuatara', 'cobra', 'elefante', 'rato', 'cachorro', 'jabuti').
@animais = keys %idade;

Há uma função parecida para os valores.

# @tempo_vida agora é (40, 35, 6, 70, 3, 12, 80).
@tempo_vida = values %idade;

Each retorna uma lista de dois elementos, contendo uma chave do hashing junto com o seu valor associado. Chamadas subsequentes  para each retornarão outro par de chave/valor até que todos os pares tenha sido retornados, nesse ponto, um array vazio será retornado.

while ( ($nome, $vida) = each %idade) ) {
print "$nome vive $vida anos\n";
}

Para saber o tamanho de um hashing basta atribuir a um scalar usando a função keys.

# o valor de $quantidade_animais é 3.
$quantidade_animais = keys %idade;

Para acessar partes de um hashing usa se a sintaxe abaixo:

# Mostra a idade da tartaruga.
$mais_velho = {'tartaruga'};

Da mesma forma que é possível dar valores a um hashing, usando uma lista é possível usar a função map para tranformar uma lista num hashing. Por exemplo, o código a seguinte cria uma hashing em que a as chaves são números e os valores seus quadrados.

%quadrado = map { $_ => ($_ * $_) } @numeros;

Segue abaixo um programa que mostra o funcionamento da variável hashing:


  1 #!/usr/bin/perl
  2
  3 use warnings;
  4 use strict;
  5
  6 my %idade;
  7 my $nome;
  8 my $idade;
  9 my $animal;
 10 my @animais;
 11 my $quantidade_animais;
 12 my %mais_velho;
 13 my @mais_velho;
 14 my %quadrado;
 15 my @numeros;
 16 my $numero;
 17 my $quadrado;
 18
 19 # Cria uma hashing vazio
 20 print "Hashing vazio:\n";
 21 %idade = ();
 22 print %idade;
 23
 24 print "\n\n";
 25
 26 # Cria um hashing com a idade dos animais usando sintaxe de virgulas
 27 print "Idade dos animais: \n";
 28 %idade = ('jabuti', 80, 'rato', 3, 'cobra', 6);
 29 while (($nome, $idade) = each %idade){
 30   print "-$nome pode viver até os $idade anos\n";
 31 }
 32
 33 print "\n\n";
 34
 35 # Adiciona mais itens ao hashing exitente usando a sintaxe de =>
 36 print "Idade dos animais: \n";
 37 %idade = (%idade, (tuatara => 35, cachorro => 12, harpia => 40));
 38 while (($nome, $idade) = each %idade){
 39   print "-$nome pode viver até os $idade anos \n";
 40 }
 41
 42 print "\n\n";
 43
 44 # Adiniciona item individualmente
 45 print "Idade dos animais:\n";
 46 $idade{elefante} = 70;
 47 while (($nome, $idade) = each %idade){
 48   print "-$nome pode viver até os $idade anos \n";
 49 }
 50
 51 print "\n\n";
 52
 53 # Acessando os dados de um hashing específicado pelo índice
 54 $animal = 'jabuti';
 55 print "A média de vida do $animal é de $idade{$animal} anos \n";
 56
 57 print "\n\n";
 58
 59 # Acessando as chaves do hashing
 60 print "Os animais são:\n";
 61 @animais = keys %idade;
 62 foreach (@animais){
 63   print "-$_ \n";
 64 }
 65
 66 print "\n\n'";
 67
 68 # Acessando os valores
 69 print "A idades dos animais:\n";
 70 @animais = values %idade;
 71 foreach (@animais){
 72   print "-$_ \n";
 73 }
 74
 75 print "\n\n";
 76
 77
 78 # Pegando o tamanho de um hashing
 79 print "Quantidade de animais:\n";
 80 $quantidade_animais = keys %idade;
 81 print $quantidade_animais;
 82
 83 print "\n\n";
 84
 85 # Acessando parte de um hashing
 86 print "Animais que vivem mais tempo:\n";
 87 @mais_velho = ('jabuti', 'elefante');
 88 foreach (@mais_velho){
 89   $mais_velho{$_} = $idade{$_};
 90 }
 91 while (($nome, $idade) = each %mais_velho){
 92   print "-$nome vive $idade anos\n";
 93 }
 94
 95 print "\n\n";
 96
 97 # Montando uma lista contendo o quadrado dos números
 98 @numeros = (1, 2, 3, 4, 5, 6);
 99 %quadrado = map { $_ => ($_ * $_) } @numeros;
100 while (($numero, $quadrado) = each %quadrado){
101   print "O quandrado de $numero é $quadrado \n";
102 }

Conectando no banco com DBI

dezembro 1, 2008 by

A interface com banco de dados no Perl é centralizada no módulo DBI. Para este módulo, existem os drivers para cada banco de dados, como DBD::mysql, DBD::pgsql, etc.

No Debian, o Mysql já instala o driver de conexão do Perl automaticamente, mas se não estivesse instalado, para pegar os pacotes da distribuição seria:

# aptitude install libdbi-perl libdbd-mysql-perl

A interface para utilização é bem simples:

#!/usr/bin/perl
 
use strict;
use warnings;
 
use DBI;
 
my $dbh = DBI->connect('dbi:mysql:wordpress', 'nobody', 'nobody');
 
my $sth = $dbh->prepare('SELECT * FROM wp_posts');
$sth->execute();
 
while ( my $row = $sth->fetchrow_hashref ) {
    print $row->{post_title}, "\n";
}

A diferença pra quem está vindo do PHP é que primeiro preparamos a query com o método prepare no objeto da conexão. O método retorna um objeto DBI::st que representa o statement, e então executamos a query com execute.

O legal na verdade é quando utilizamos parâmetros. Preparamos a query com placeholders e passamos os parâmetros pro execute.

Além de evitar preocupação com escapar os dados, queries que serão executadas mais de uma vez com parâmetros diferentes são preparadas uma única vez, com ganhos de performance consideráveis em alguns SGBDs.

$sth = $dbh->prepare('
    SELECT * FROM wp_posts
    WHERE post_author = ?
      AND post_title = ?
');
 
$sth->execute(1, 'Hello world!');
printf "Total de hello world: %d\n", $sth->rows;
 
$sth->execute(1, 'Teste');
printf "Total de teste: %d\n", $sth->rows;

E é isso. Post rápido só pra dar base pra alguma aplicação que a gente queira testar mais pra frente.

Veja a documentação da API pra detalhes interessantes:
http://search.cpan.org/~timb/DBI-1.607/DBI.pm

Obs: Sabe-se que, pelo menos até a versão 5.0, o query cache não funciona no MySQL se utilizado com prepared statements. Já o Oracle consegue guardar o plano de execução, evitando ter que determinar a melhor estragégia de busca a cada query. Com prepared statements o plano de execução fica em cache indepentente dos parâmetros, conseguindo um ganho significativo de performance.

Instruções básicas de Perl

novembro 24, 2008 by

Executando Perl

Inicialmente devemos criar um arquivo com a extensão .pl
Nas primeira linha devemos colocar a instrução abaixo:
#!/usr/bin/perl

Esta instrução é o caminho do interpretador do Perl.

para executar devemos usar a instrução abaixo:
$ perl exec1.pl

ou

$ ./exec1.pl

já que mencionamos o interpretador na primeira linha, lembrado de dar permissão para execução.

Seguem algumas instruções de linha de comando úteis

-w -> Solicita à Perl para avisar se há pratica de programação perigosa, pode ser usado “use warnings;”, mas só seŕa avisado dentro do contexto.
-T -> Ativa o modo “taint” da Perl. Neste modo toda entra de uma fonte externa é colocada em dúvida por padrão.
-c -> Verfica os erros de sintaxe de um script sem executar.
-d -> Executa o script usando um depurador imbutido da Perl.
-e -> Esta opção é usada quando define se que uma string seja o código a sere executado.

Scalar

Uma variável de scalar mantém apenas um único item dos dados.
Toda variável de scalar é precedida de $.

$texto = 'Ola mundo!';
$contador = 100;
$contador = 'Cem';

Em Perl a mesma variável pode conter texto e números a Perl se encarrega de converter conforme o contexto.

Questão das aspas.
Se uma string está entre aspas duplas  e contém nomes de variáveis, então essas variáveis são  substituidas por seus  valores no final da string.
Se a string está entre apóstrofes, então a subistituição da variável não ocorrerá.
É importante ressaltar que usando aspas duplas é possível usar os caracteres de especiais, como o \n \t entre outros.

O exemplo abaixo exemplifica o uso da aspas.


 1 #!/usr/bin/perl
 2
 3 use warnings;
 4 use strict;
 5
 6 my $marido,
 7 my $mulher;
 8 my $filha;
 9 my $mensagem1;
10 my $mensagem2;
11
12 $marido = "Dyego";
13 $mulher = "Vanessa";
14 $filha = "Beatriz";
15
16 $mensagem1 = "O $marido ama muito a $mulher e a $filha.\n";
17 $mensagem2 = 'O $marido ama muito a $mulher e a $filha.\n';
18
19
20 # imprime: O Dyego ama muito a Vanessa e a Beatriz.
21 print $mensagem1;
22
23 # imprime: O $marido ama muito a $mulher e a $filha.\n
24 print $mensagem2;

Array

Um array contém uma lista de valores scalars ordenados
Um array é precedido de @

@vazio = ();
@mamiferos = ('macaco', 'elefante', 'urso');
@repteis = ('jacaré', 'tartaruga', 'lagarto');
@animais = (@mamiferos, @repteis); # Obtém um array de de seis elementos.
($carnivoro, $hebivoro, $onivoro) = @repteis;

Para acessar os elementos do array dever ser usada a sintaxe abaixo:

$array[0]

Esta sintaxe pode ser usada para estabelecer e atribuir valor para um scalar.

$paquiderme = $mamiferos[1]; # valor é elefante

Quanto trabalhamos com o valor individual de array usamos o prefixo de um scalar $.

É possível acessar os últimos valores de um array usando o índice negativo.

$maritimo = $repteis[-2]; # valor é tartaruga

Para obter o tamanho de um array basta atribuir o array a um scalar.

$qtde = @animais; # valor retornado é 6

Há uma sutil diferença entre uma lista de um array

$contador = @repteis; # O conteúdo de $contador é 3
$ultimo = ('macaco', 'usro'); # O conteúdo de $ultimo é 'urso'

Algumas funções para manipulação de arrays

  • push – Acrescenta os elementos da lista ao final do array. (push ARRAY, LIST)
  • pop – Remove e retorna o último elementos do array. (pop ARRAY)
  • shift – Remove e retorna o primeiro elemento do array. (shift ARRAY)
  • unshift – Acrescenta os elementos da lista na frente do array. (unshift ARRAY, LIST)
  • splice – Remove e retorna os elementos LENGTH do ARRAY que começa no elemento OFFSET e os substitui pelos elementos da LIST. Se LIST for omitida então os elementos removidos serão simplesmente apagados. se LENGTH for omitido então tudo desde OFFSET até o final do ARRAY será removido. (splice ARRAY, OFFSET, LENGTH, LIST)

Map e Grep são outras listas bastante úteis de processamento de funções.

  • map – Executa o código e monta a lista com os valores de retorno sem avaliar se é verdadeiro
  • grep – Executa o código e monta a lista com os valores avaliando se o código retornado é verdadeiro.

Criando uma lista de quandrados

@numeros = (1..10);
@quadrados = map { $_ * $_ } @numeros;

Cria uma lista do os valores impares

@impares = grep { $_ % 2 } @numeros;

Abaixo segue um código que mostra o uso de arrays:


  1 #!/usr/bin/perl
  2
  3 use warnings;
  4 use strict;
  5
  6 my @vazio;
  7 my @mamiferos;
  8 my @repteis;
  9 my @animais;
 10 my $carnivoro;
 11 my $herbivoro;
 12 my $onivoro;
 13 my $paquiderme;
 14 my $maritimo;
 15 my $qtde;
 16 my $contador;
 17 my $ultimo;
 18 my $resultado;
 19 my @numeros;
 20 my @quadrados;
 21 my @impares;
 22
 23 # Imprime o array @vazio
 24 @vazio = ();
 25 print "Vazio:\n";
 26 print @vazio;
 27
 28 print "\n\n";
 29
 30 # Imprime o array @mamiferos
 31 @mamiferos = ('macaco', 'elefante', 'urso');
 32 print "Mamiferos:\n";
 33 foreach (@mamiferos){
 34   print "- $_ \n";
 35 }
 36 print "\n\n";
 37
 38 # Imprime o array @repteis
 39 @repteis = ('jacaré', 'tartaruga', 'lagarto');
 40 print "Repteis: \n";
 41 foreach (@repteis){
 42   print "- $_ \n";
 43 }
 44 print "\n\n";
 45
 46 # Imprime o array @animais
 47 @animais = (@mamiferos, @repteis); # Obtém um array de de seis elementos.
 48 print "Animais:\n";
 49 foreach(@animais){
 50   print "- $_ \n";
 51 }
 52 print "\n\n";
 53
 54 # Imprime os conteúdos do array atribuido as variáveis scalar
 55 ($carnivoro, $herbivoro, $onivoro) = @repteis;
 56 print "Carnivoro: $carnivoro \n";
 57 print "Herbivoro: $herbivoro \n";
 58 print "Onivoro: $onivoro \n";
 59
 60 print "\n\n";
 61
 62 # Imprime urso
 63 print "Imprime o 3º elemento do array animais: ";
 64 print $animais[2];
 65
 66 print "\n\n";
 67
 68 # Imprime Elefante
 69 print "Paquiderme: ";
 70 $paquiderme = $mamiferos[1];
 71 print $paquiderme;
 72
 73 print "\n\n";
 74
 75 # Imprime Tartaruga
 76 print "Réptil marítimo: ";
 77 $maritimo = $repteis[-2];
 78 print $maritimo;
 79
 80 print "\n\n";
 81
 82 # Imprime o tamanho do array
 83 $qtde = @animais;
 84 print "Temos $qtde animais.";
 85
 86 print "\n\n";
 87
 88 # Mostra a diferença entre lista e array
 89 $contador = @repteis; # O conteúdo de $contador é 3
 90 print "Temos $contador repteis \n";
 91 =comment
 92   O conteúdo de $ultimo é 'urso' e apresenta uma mensagem de erro,
 93   pois está sendo atribuido somente o último item, o correto é usar um array para receber a lista.
 94 =cut
 95 $ultimo = ('macaco', 'usro');
 96 print "Último item da lista: $ultimo";
 97
 98 print "\n\n";
 99
100 # Push - Acrescenta os elementos da lista ao final do array
101 push @repteis, ('cobra', 'iguana', 'camaleão');
102 print "Mais repteis: \n";
103 foreach (@repteis){
104   print "- $_ \n";
105 }
106
107 print "\n\n";
108
109 # pop - Remove e retorna o último elementos do array
110 $resultado = pop @mamiferos;
111 print "Foi retirado o $resultado da lista de mamiferos:\n";
112 foreach (@mamiferos){
113   print "- $_ \n";
114 }
115
116 print "\n\n";
117
118 # shift - Remove e retorna o primeiro elemento do array.
119 $resultado = shift @repteis;
120 print "Foi removido o $resultado da lista de repteis: \n";
121 foreach (@repteis){
122   print "- $_ \n";
123 }
124
125 print "\n\n";
126
127 # unshift - Acrescenta os elementos da lista na frente do array.
128 unshift @animais, ('arara', 'pavao', 'tucano');
129 print "Mais animais: \n";
130 foreach (@animais){
131   print "- $_ \n";
132 }
133
134 print "\n\n";
135
136 =comment
137   splice - Remove e retorna os elementos LENGTH do ARRAY que começa no elemento OFFSET
138            e os substitui pelos elementos da LIST
139 =cut
140 splice @animais, 0, 3, ('garça', 'harpia', 'gavião');
141 print "Alteradas as aves da lista de animais: \n";
142 foreach (@animais){
143   print "- $_ \n";
144 }
145
146 print "\n\n";
147
148 # map - Executa o código e monta a lista com os valores de retorno sem avaliar se é verdadeiro
149 @numeros = (1..10);
150 print "Números inteiros: \n";
151 foreach (@numeros){
152   print "$_, ";
153 }
154 @quadrados = map  { $_ * $_ } @numeros;
155 print "\nO quadrado dos números acima:\n";
156 foreach (@quadrados){
157   print "$_, ";
158 }
159
160 print "\n\n";
161
162 # grep - Executa o código e monta a lista com os valores avaliando se o código retornado é verdadeiro.
163 print "Mosta os números ímpares:\n";
164 @impares = grep { $_ % 2 } @numeros;
165 foreach (@impares){
166   print "$_ , ";
167 }
168
169 print "\n\n";

Variáveis do GET e POST no Perl

novembro 18, 2008 by

Dando continuidade à tentativa de fazer algo web com Perl, acho que o próximo passo pode ser receber parâmetros vindos de um formulário ou url.

O primeiro script de teste ficou assim:

use strict;
use warnings;
 
my $r = shift;
 
$r->content_type('text/html');
 
print '<h1>Funcionou!</h1>';

O script é executado pelo modperl como se fosse uma função e recebe como parâmetro um objeto do tipo Apache2::RequestRec. Quando fazemos o shift, este parâmetro passa para a variável local $r.

Para ter acesso aos dados submetidos por GET ou POST de forma legível, precisamos instanciar um objeto Apache2::Request, que recebe no construtor o RequestRec da requisição atual:

use strict;
use warnings;
 
use Apache2::Request;
 
my $r = shift;
my $req = Apache2::Request->new($r);
 
$r->content_type('text/html');
 
print '<h1>Funcionou!</h1>';

Os parâmetros passados, tanto por GET quanto por POST, estão disponíveis pelo accessor param:

use strict;
use warnings;
 
use Apache2::Request;
 
my $r = shift;
my $req = Apache2::Request->new($r);
 
$r->content_type('text/html');
 
print '<h1>Funcionou!</h1>';
 
print $req->param('variavel_por_get');
print $req->param('variavel_por_post');

Caso o nome da variável não seja passado para o accessor, ele retorna um array que pode ser iterado, como neste caso:

use strict;
use warnings;
 
use Apache2::Request;
 
my $r = shift;
my $req = Apache2::Request->new($r);
 
$r->content_type('text/html');
 
foreach my $param ( $req->param ) {
    print "$param: ", $req->param($param), "<br />";
}

Além do accessor param, os dados do POST também estão no accessor body. Para acessar uma variável exclusivamente submetida por POST fica assim:

use strict;
use warnings;
 
use Apache2::Request;
 
my $r = shift;
my $req = Apache2::Request->new($r);
 
$r->content_type('text/html');
 
print '<h1>Funcionou!</h1>';
 
print $req->body('somente_variavel_por_post');

Assim como no param, também é possível ter um array com o nome dos parâmetros passados por POST ao acessar o body sem nenhum argumento.

E é isso.

Referências:

Parâmetros de funções em Perl

novembro 14, 2008 by

Uma coisa que ainda me irrita um pouco é a falta de assinatura de funções em Perl. Quando eu já estava me acostumando com parâmetros tipados e começava a desejar type hint para retorno de métodos, no Perl parece que não temos nada disso.

Os argumentos de funções chegam no array @_. Dentro da função você precisa pegar os argumentos dessa lista e fazer as validações necessárias.

Exemplo:
sub escrever_dados {
    my ($nome, $cidade) = @_;
    print "Nome: $nome, cidade: $cidade\n";
}
 
escrever_dados('Mary', 'Rio de Janeiro');

A função nesse caso recebe uma lista e os seus elementos são passados para as variáveis locais.

O que mais me incomoda é que parâmetros a mais ou a menos na chamada à função não resultam em erro algum. O que pode ser feito é validar dentro da função a quantidade e tipo dos parâmetros, mas torna o código extremamente repetitivo e mais sujeito a erros.
sub escrever_dados {
    if (scalar @_ != 2) {
        print "Função espera 2 argumentos\n";
        return 0;
    }
    my ($nome, $cidade) = @_;
    print "Nome: $nome, cidade: $cidade\n";
}
 
escrever_dados('Mary', 'Rio de Janeiro', 'Vai dar erro');
escrever_dados('Também vai dar erro');
escrever_dados(); # Lista vazia (scalar 0) também dá erro

A não ser que alguém conheça uma forma melhor. Alguém? Alguém?

Como o @_ é uma lista normal, qualquer forma de acesso é válida:
sub saudacao {
    my $nome = shift;
    print "Oi, $nome!\n";
}
 
saudacao('Mundo');

sub erro {
    die "Erro inesperado $_[0]\n";
}
 
erro('Valor inválido!');

Mas ainda acho que associar as variáveis na forma my ($nome, $cidade) = @_; fica mais claro. Exceto quando estamos trabalhando com objetos, aí acho mais claro fazer my $self = shift; antes. Mas aí já é outra história.

Divirta-se.