Contexto de la llamada

Cuando se llama a una subrutina, es posible detectar si se esperaba un valor escalar, una lista o nada. Estas posibilidades definen tres contextos en los cuales una subrutina puede ser llamada. Por ejemplo:
listdir(@files); # contexto void
$listed = listdir(@files); # contexto escalar
@missing = listdir(@files); # contexto de lista
($f1, $f2) = listdir(@files); # contexto de lista
print (listdir(@files)); # contexto de lista

Esta información puede obtenerse mediante la función wantarray. Esta función devuelve:

Podemos utilizar esta información para seleccionar la información apropiada a utilizar en la sentencia return. El siguiente programa suprime los espacios en blanco al comienzo y al final de la variable:

   1 #!/usr/bin/perl -w
   2 my @many = (" one ", "  two  ", "   three   ");
   3 my $string = "\n\nstring\n\n";
   4 print "string = $string\n";
   5 print "many = (@many)\n";
   6 $string = trim($string);
   7 @many = trim(@many);
   8 print "string = $string\n";
   9 print "many = (@many)\n";
  10 
  11 sub trim {
  12   my @out = @_;
  13 
  14   for (@out) {
  15     s/^\s+//;
  16     s/\s+$//;
  17   }
  18   return wantarray? @out : $out[0];
  19 }
  20
Ejemplo de ejecución:
> trim.pl
string =

string


many = ( one    two      three   )
string = string
many = (one two three)

El Módulo Contextual::Return

Se puede obtener una información mas detallada sobre el contexto de la llamada usando el módulo Contextual::Return:

pl@nereida:~/src/perl/testing$ cat contextual.pl
#!/usr/local/bin/perl -w
use strict;
use Contextual::Return;

sub sensible {
  return STR { "one" }
         NUM { 1 }
  ;
}

print "Result = ".sensible()."\n";
print "Result = ".(0+sensible())."\n";
Al ejecutar este programa obtenemos:
pl@nereida:~/src/perl/testing$ contextual.pl
Result = one
Result = 1

Contextual::Return tambien permite crear variables contextuales multitipo con mas de dos tipos (a diferencia de dualvar que está restringida a los tipos cadena y número):

lhp@nereida:~/Lperl/src/testing$ cat -n context1.pl
 1  #!/usr/local/bin/perl -w
 2  use strict;
 3  use Contextual::Return;
 4
 5  my $x = BOOL { 0 } NUM { 3.14 } STR { "pi" };
 6
 7  unless ($x) { warn "¡El famoso número $x (".(0+$x).") pasa a ser falso!\n" } # executed!
lhp@nereida:~/Lperl/src/testing$ context1.pl
¡El famoso número pi (3.14) pasa a ser falso!

Si se usa la etiqueta ACTIVE el código de definición será ejecutado cada vez que la variable multiestado es evaluada. Por ejemplo:

lhp@nereida:~/Lperl/src/testing$ cat -n context2.pl
1  #!/usr/local/bin/perl -w
2  use strict;
3  use Contextual::Return;
4
5  my $now = ACTIVE NUM { time } STR { localtime };
6
7  print "Now: $now (".($now+0).")\n";
8  sleep(1);
9  print "Now: $now (".($now+0).")\n";

La ejecución del programa produce una salida como esta:

lhp@nereida:~/Lperl/src/testing$ context2.pl
Now: Sat Mar 15 11:45:58 2008 (1205581558)
Now: Sat Mar 15 11:45:59 2008 (1205581559)



Subsecciones
Casiano Rodríguez León
2009-10-04