martes, 27 de agosto de 2013

Perl: Paso de parámetros por referencia

Paso de parámetros por referencia en Perl

Cuando invocamos una subrutina y le pasamos parámetros en realidad le estamos pasando una lista de datos, que se llama @_ . Cuando pasamos vectores (matrices, arreglos o arrays ) o tablas asociativas ( hashes ) como parámetros, en realidad los estamos introduciendo, elemento por elemento, en @_ . La forma más económica de pasar parámetros a subrutinas es pasarlos por referencia. De esta manera no pasamos los datos en sí, si no la dirección que ocupan en memoria. Así no es necesario enumerar y copiar todos los datos a @_, y evitar los problemas de pasar varios hashes o arreglos, y la subrutina que reciba las referencias puede acceder a los datos en su organización original, ya sean escalares, vectores o tablas asociativas, las tres clases de variables en Perl. Por otro lado el paso por referencia permite modificar de forma permanente, no local, los datos pasados como argumento.

1) Ejemplo de paso por referencia

#
# Ejemplo de paso de parámetros por referencia en Perl:
# ¿Como pasar parámetros por referencia y modificar los valores?
# How to pass parameters by reference in perl, modify the values​​?
#This is perl 5, version 14, subversion 2 (v5.14.2)
#!/usr/bin/perl

#use strict;
#use warnings;

my $param = "algo";
my @vector1 = (1,2,3);
function_with_params(\$param, \@vector1);
print "\n";
print $param;
print "\n";
print $vector1[0];
print "\n";

sub function_with_params{
    my ($arg1, $arg2) = @_;
    ${$arg1} = "changed...";
    @{$arg2}[0]=33;    #vector1
    return;
    }

2) Ejemplo de paso por referencia de un array.

#!/usr/bin/perl
use strict;
use warnings;

print "Ejemplo perl de paso por referencia de un array... \n";

my @airlines_travel = ("a","b","b","c","k");
my $arrayRef = \@airlines_travel; #referencia al array
my $string = "b";

print "Count: " . howManyTimesIsString($string, $arrayRef) . "\n";

# Cuenta cuantas veces esta un string en un array
sub howManyTimesIsString {
 my ($string, $arrayRef) = @_;
 my $count = 0;
 foreach my $item (@{$arrayRef}) {
   if ($string eq $item) {
      $count++;
   }
 }
 return $count;
}

3) POO y paso por referencia.


En perl todos los objetos son una referencia. Es decir, cuando tenes un $obj es una variable scalar que simplemente mantiene la referencia al objeto. Cuando pasamos un objeto como parámetro lo que estamos pasando es su referencia (no es necesario hacer nada extraño para explicitar esto).

También se puede explicitar usando \variableObject y $$variableObject pero no es recomendable usarlo de esta manera. A continuación un ejemplo de esta forma:

#This is perl 5, version 14, subversion 2 (v5.14.2)
#...

sub metodo1{
  my ($self) = @_;

  my $obj = Example->new();
  my $o = $self->metodo2(\$obj);
  print $o->getName();
  return;
}

sub metodo2{
  my ($self, $obj) = @_;
#...
  print $$obj->encodeHTMLtoUTF8($str);
  $$obj->setName("modificado");
  return $$obj;
}



Referencias:
-Paso de parámetros por valor y por referencia (Perl).
-Blog: Parametros por referencia en perl.