Perl - Subrutinas

Una subrutina o función de Perl es un grupo de declaraciones que juntas realizan una tarea. Puede dividir su código en subrutinas separadas. La forma en que divide su código entre las diferentes subrutinas depende de usted, pero lógicamente la división suele ser para que cada función realice una tarea específica.

Perl usa los términos subrutina, método y función indistintamente.

Definir y llamar una subrutina

La forma general de una definición de subrutina en el lenguaje de programación Perl es la siguiente:

sub subroutine_name {
   body of the subroutine
}

La forma típica de llamar a esa subrutina de Perl es la siguiente:

subroutine_name( list of arguments );

En las versiones de Perl anteriores a la 5.0, la sintaxis para llamar a subrutinas era ligeramente diferente, como se muestra a continuación. Esto todavía funciona en las versiones más recientes de Perl, pero no se recomienda ya que omite los prototipos de subrutinas.

&subroutine_name( list of arguments );

Echemos un vistazo al siguiente ejemplo, que define una función simple y luego la llamamos. Debido a que Perl compila su programa antes de ejecutarlo, no importa dónde declare su subrutina.

#!/usr/bin/perl

# Function definition
sub Hello {
   print "Hello, World!\n";
}

# Function call
Hello();

Cuando se ejecuta el programa anterior, produce el siguiente resultado:

Hello, World!

Pasar argumentos a una subrutina

Puede pasar varios argumentos a una subrutina como lo hace en cualquier otro lenguaje de programación y se puede acceder a ellos dentro de la función usando la matriz especial @_. Por tanto, el primer argumento de la función está en $ _ [0], el segundo está en $ _ [1], y así sucesivamente.

Puede pasar matrices y hashes como argumentos como cualquier escalar, pero pasar más de una matriz o hash normalmente hace que pierdan sus identidades separadas. Entonces usaremos referencias (explicadas en el próximo capítulo) para pasar cualquier matriz o hash.

Probemos con el siguiente ejemplo, que toma una lista de números y luego imprime su promedio:

#!/usr/bin/perl

# Function definition
sub Average {
   # get total number of arguments passed.
   $n = scalar(@_);
   $sum = 0;

   foreach $item (@_) {
      $sum += $item;
   }
   $average = $sum / $n;

   print "Average for the given numbers : $average\n";
}

# Function call
Average(10, 20, 30);

Cuando se ejecuta el programa anterior, produce el siguiente resultado:

Average for the given numbers : 20

Pasar listas a subrutinas

Dado que la variable @_ es una matriz, se puede utilizar para suministrar listas a una subrutina. Sin embargo, debido a la forma en que Perl acepta y analiza listas y matrices, puede resultar difícil extraer los elementos individuales de @_. Si tiene que pasar una lista junto con otros argumentos escalares, haga una lista como último argumento como se muestra a continuación:

#!/usr/bin/perl

# Function definition
sub PrintList {
   my @list = @_;
   print "Given list is @list\n";
}
$a = 10;
@b = (1, 2, 3, 4);

# Function call with list parameter
PrintList($a, @b);

Cuando se ejecuta el programa anterior, produce el siguiente resultado:

Given list is 10 1 2 3 4

Pasando hashes a subrutinas

Cuando proporciona un hash a una subrutina u operador que acepta una lista, el hash se traduce automáticamente en una lista de pares clave / valor. Por ejemplo

#!/usr/bin/perl

# Function definition
sub PrintHash {
   my (%hash) = @_;

   foreach my $key ( keys %hash ) {
      my $value = $hash{$key};
      print "$key : $value\n";
   }
}
%hash = ('name' => 'Tom', 'age' => 19);

# Function call with hash parameter
PrintHash(%hash);

Cuando se ejecuta el programa anterior, produce el siguiente resultado:

name : Tom
age : 19

Devolución de valor de una subrutina

Puede devolver un valor de una subrutina como lo hace en cualquier otro lenguaje de programación. Si no está devolviendo un valor de una subrutina, el último cálculo realizado en una subrutina también será automáticamente el valor de retorno.

Puede devolver matrices y hashes de la subrutina como cualquier escalar, pero devolver más de una matriz o hash normalmente hace que pierdan sus identidades separadas. Entonces usaremos referencias (explicadas en el próximo capítulo) para devolver cualquier matriz o hash de una función.

Probemos con el siguiente ejemplo, que toma una lista de números y luego devuelve su promedio:

#!/usr/bin/perl

# Function definition
sub Average {
   # get total number of arguments passed.
   $n = scalar(@_);
   $sum = 0;

   foreach $item (@_) {
      $sum += $item;
   }
   $average = $sum / $n;

   return $average;
}

# Function call
$num = Average(10, 20, 30);
print "Average for the given numbers : $num\n";

Cuando se ejecuta el programa anterior, produce el siguiente resultado:

Average for the given numbers : 20

Variables privadas en una subrutina

Por defecto, todas las variables en Perl son variables globales, lo que significa que se puede acceder a ellas desde cualquier parte del programa. Pero puedes crearprivate variables llamadas lexical variables en cualquier momento con el my operador.

los myEl operador limita una variable a una región particular de código en la que se puede utilizar y acceder a ella. Fuera de esa región, no se puede utilizar ni acceder a esta variable. Esta región se llama ámbito de aplicación. Un ámbito léxico suele ser un bloque de código con un conjunto de llaves alrededor, como las que definen el cuerpo de la subrutina o las que marcan los bloques de código de las declaraciones if, while, for, foreach y eval .

A continuación se muestra un ejemplo que le muestra cómo definir una variable privada única o múltiples utilizando my operador -

sub somefunc {
   my $variable; # $variable is invisible outside somefunc()
   my ($another, @an_array, %a_hash); # declaring many variables at once
}

Veamos el siguiente ejemplo para distinguir entre variables globales y privadas:

#!/usr/bin/perl

# Global variable
$string = "Hello, World!";

# Function definition
sub PrintHello {
   # Private variable for PrintHello function
   my $string;
   $string = "Hello, Perl!";
   print "Inside the function $string\n";
}
# Function call
PrintHello();
print "Outside the function $string\n";

Cuando se ejecuta el programa anterior, produce el siguiente resultado:

Inside the function Hello, Perl!
Outside the function Hello, World!

Valores temporales a través de local ()

los localse utiliza principalmente cuando el valor actual de una variable debe ser visible para las subrutinas llamadas. Un local solo da valores temporales a las variables globales (es decir, paquete). Esto se conoce como alcance dinámico . El alcance léxico se realiza con my, que funciona más como las declaraciones automáticas de C.

Si se le da más de una variable o expresión a local, deben colocarse entre paréntesis. Este operador funciona guardando los valores actuales de esas variables en su lista de argumentos en una pila oculta y restaurándolos al salir del bloque, subrutina o eval.

Veamos el siguiente ejemplo para distinguir entre variables globales y locales:

#!/usr/bin/perl

# Global variable
$string = "Hello, World!";

sub PrintHello {
   # Private variable for PrintHello function
   local $string;
   $string = "Hello, Perl!";
   PrintMe();
   print "Inside the function PrintHello $string\n";
}
sub PrintMe {
   print "Inside the function PrintMe $string\n";
}

# Function call
PrintHello();
print "Outside the function $string\n";

Cuando se ejecuta el programa anterior, produce el siguiente resultado:

Inside the function PrintMe Hello, Perl!
Inside the function PrintHello Hello, Perl!
Outside the function Hello, World!

Variables de estado a través de state ()

Hay otro tipo de variables léxicas, que son similares a las variables privadas pero mantienen su estado y no se reinicializan en múltiples llamadas de las subrutinas. Estas variables se definen utilizando elstate operador y disponible a partir de Perl 5.9.4.

Veamos el siguiente ejemplo para demostrar el uso de state variables -

#!/usr/bin/perl

use feature 'state';

sub PrintCount {
   state $count = 0; # initial value

   print "Value of counter is $count\n";
   $count++;
}

for (1..5) {
   PrintCount();
}

Cuando se ejecuta el programa anterior, produce el siguiente resultado:

Value of counter is 0
Value of counter is 1
Value of counter is 2
Value of counter is 3
Value of counter is 4

Antes de Perl 5.10, tendría que escribirlo así:

#!/usr/bin/perl

{
   my $count = 0; # initial value

   sub PrintCount {
      print "Value of counter is $count\n";
      $count++;
   }
}

for (1..5) {
   PrintCount();
}

Contexto de llamada de subrutina

El contexto de una subrutina o declaración se define como el tipo de valor de retorno que se espera. Esto le permite utilizar una única función que devuelve diferentes valores en función de lo que el usuario espera recibir. Por ejemplo, el siguiente localtime () devuelve una cadena cuando se llama en contexto escalar, pero devuelve una lista cuando se llama en contexto de lista.

my $datestring = localtime( time );

En este ejemplo, el valor de $ timestr ahora es una cadena formada por la fecha y hora actuales, por ejemplo, Thu Nov 30 15:21:33 2000. A la inversa,

($sec,$min,$hour,$mday,$mon, $year,$wday,$yday,$isdst) = localtime(time);

Ahora las variables individuales contienen los valores correspondientes devueltos por la subrutina localtime ().