Back-End

24 set, 2008

Criando e usando uma função em Perl

Publicidade

A definição de blocos de código que possam ser reutilizados é um recurso presente na imensa maioria das linguagens de programação, favorecendo o reaproveitamento de código, garantindo que trechos de códigos já testados tenham uma melhor qualidade e o tempo de desenvolvimento seja diminuído (pensando que um conjunto de componentes esteja disponível). Em Perl, essa possibilidade está presente e é extremamente flexível.


@conjunto = (10, 20, 30, 40);
&imprime_vetor(@conjunto);
print "\npos impressao";
 
sub imprime_vetor {
  my @dados = @_;
 
  print join(' ', @dados);
}

No trecho acima, foi definida uma função que recebe como parâmetro um conjunto de dados (vetor), imprime os valores separados por espaço e retorna para o ponto em que ela foi chamada. Repare que essa função não retorna qualquer tipo de valor, tendo o comportamento próximo do existente nos chamados procedimentos de outras linguagens de programação. Veja também que a chamada é feita precedendo o nome da função com um “e-comercial”, deixando explícita a chamada à função.

Dentro dessa função, foi definida uma variável local (só existe dentro da função) e ela recebe uma cópia do valor passado como argumento. Naquele contexto, deve-se trabalhar com a cópia local, evitando que modificações no original sejam propagadas. Repare que na definição da função é utilizada a palavra reservada sub e que diferente de outras linguagens de programação, na definição da função não aparecem eventuais parâmetros de entrada. Para tanto, existe uma variável especial, a @_, que faz e armazena todos os parâmetros passados como argumento. O corpo da função é delimitado pelas chaves.

 
sub retorna_maior {
  my $primeiro = $_[0];
  my $segundo = $_[1];
 
  if ($primeiro >= $segundo) {
    return $primeiro;
 
  } else {
    return $segundo;
 
  }
 
} # retorna_maior

print &retorna_maior(7, 16);

A função mostra que mesmo que o trecho de código retorne algum tipo de informação, não se deve colocar na sua definição o retorno, ficando subentendido qual o tipo e valor retornado. Além disso, o vetor de entrada foi acessado individualmente em cada uma de suas posições, sendo colocado os valores dentro das variáveis $primeiro e $segundo. Repare também que a definição da função pode ser colocada depois da sua eventual chamada.

Funções podem ser tão complexas quanto se possa desejar ou imaginar, ainda que quanto mais linhas de código ela tiver, mais complexa será sua manutenção e entendimento. Ainda que o Perl permita, deve-se evitar ao máximo acessar variáveis de escopo maior (globais ou da página) dentro de funções sem que essas tenham sido passadas como argumento, pois resultados inesperados podem acontecer em outros trechos de código e cuja rastreabilidade fica seriamente comprometida. Repare nos seguintes blocos de código:


$a = "ABC";
 
sub usa_a {
  print $a;
}

usa_a;

O resultado será a impressão do termo “ABC” (repare que o e-comercial e os parênteses foram omitidos), variável essa que foi definida fora do escopo da função. Veja uma modificação no código:


$a = "ABC";
 
sub usa_a {
  print $a;
  $a = 2;
}

usa_a;
print $a;

Agora, a função será chamada, o valor corrente impresso (ABC), o seu valor trocado e em seguida impresso, resultado ao final em ABC2. Assim, dentro da função, o valor de uma variável de escopo maior foi alterado, impactando em eventuais processamentos que forem feitos depois. Uma outra modificação:


$a = "ABC";
 
sub usa_a {
  print $a;
  my $a = 2;
}

usa_a;
print $a;

Esse exemplo é bem próximo do anterior, mas foi acrescentado o termo “my” à variável $a, tornando-a local à função. Sendo assim, qualquer modificação realizada dentro da função não terá reflexo externo, tornando o código mais seguro, pois não existirá o risco de modificações indesejadas serem feitas na função e estas se propagarem para os demais trechos do código.