Skip to content

Latest commit

 

History

History
886 lines (602 loc) · 48.3 KB

perlsyn.pod

File metadata and controls

886 lines (602 loc) · 48.3 KB

NOMBRE

perlsyn - Sintaxis de Perl

DESCRIPCIÓN

Un programa Perl consiste en una secuencia de declaraciones y sentencias que se ejecutan de arriba hacia abajo. Bucles, subrutinas y otras estructuras de control le permiten saltar a lo largo del código.

Perl es un lenguaje de estructura libre: puede formatearlo y sangrarlo como quiera. El espacio en blanco sirve para separar los tokens, a diferencia de lenguajes como Python donde es una parte importante de la sintaxis, o de Fortran, donde es inmaterial.

Muchos de los elementos sintácticos de Perl son opcionales. En vez de obligarle a poner paréntesis en todas las llamadas de función y declarar cada variable, puede, a menudo, dejar algunos elementos de forma explícita, y Perl intentará adivinar lo que quiere decir. Esto es conocido como Do What I Mean (haz lo que te digo), abreviado como DWIM. Permite a los programadores ser perezosos y codificar en el estilo en que se encuentran más cómodos.

Perl toma prestada la sintaxis y conceptos de muchos lenguajes: awk, sed, C, Bourne Shell, Smalltalk, Lisp e incluso el Inglés. Otros lenguajes han tomado prestada la sintaxis de Perl, particularmente sus extensiones de expresiones regulares. Así que si ha programado en otro lenguaje verá partes en Perl que le serán familiares. A menudo funcionan de la misma forma, pero mire perltrap para ver cómo difieren.

Declaraciones

Los únicos elementos que necesita declarar en Perl son los informes y las subrutinas (y algunas veces ni siquiera las subrutinas). Una variable escalar almacena el valor indefinido (undef) hasta que se le asigna un valor definido, que es cualquier otra cosa distinta de undef. Cuando se usa como un número, undef es tratado como si fuera 0; cuando se usa como una cadena de caracteres (string), se trata como la cadena vacía, ""; y cuando se usa como una referencia que no ha sido asignada, es tratado como un error. Si ha activado los avisos (warnings), será notificado de un valor no inicializado cada vez que trate a undef como si fuera una cadena o número. Bueno, normalmente. En contextos booleanos, como en:

if ($a) {}

están exentos de esos avisos (porque tienen en cuenta el valor de verdad en vez de ver si está definido). Operadores como ++, --, +=, -= y .=, que operan sobre valores indefinidos como en:

undef $a;
$a++;

están también exentos de tales avisos.

Una declaración puede ponerse en cualquier sitio, como si fuera una instrucción, pero no tiene efecto en la ejecución de la secuencia de instrucciones principal: todas las declaraciones toman efecto en tiempo de compilación. Todas las declaraciones se suelen poner al principio o al final del script. Sin embargo, si está usando variables privadas en un contexto local creadas con my(), state() u our(), deberá asegurarse que su definición de formato o subrutina están dentro del mismo bloque que el my si quiere acceder a estas variables privadas.

Declarar una subrutina permite que su nombre sea usado como si fuera un operador de lista, desde el punto de vista del programa. Puede declarar una subrutina sin definirla diciendo sub nombre, como:

sub mi_nombre;
$yo = mi_nombre $0          or die "no puedo obtener mi_name";

Una declaración simple como ésta declara que la función es un operador de lista, no un operador unario, así que tiene que tener cuidado a la hora de usar paréntesis (o or en lugar de ||). El operador || se enlaza con firmeza al final de la lista de operadores; se convierte en parte del último elemento. Siempre puede usar paréntesis alrededor de los argumentos de los operadores de lista para convertir el operador de lista de nuevo en algo que se comporta más como una llamada de función. De forma alternativa, puede utilizar el prototipo ($) para convertir la subrutina en un operador unario:

sub minombre ($);
$me = minombre $0               || die "no puedo obtener minombre";

Ahora se analiza como era de esperar, pero aún debe adquirir el hábito de uso de los paréntesis en esa situación. Para más información sobre prototipos, vea perlsub.

Las declaraciones de subrutinas pueden cargarse también con la instrucción require o cargadas e importadas en su espacio de nombres con la instrucción use. Ver perlmod para detalles sobre esto.

Una secuencia de instrucciones pueden contener declaraciones de variables en ámbito léxico (privado), pero, aparte de declarar un nombre de variable, la declaración actúa como una instrucción normal y es elaborada dentro de la secuencia de instrucciones como si fuera una instrucción normal. Esto significa que realmente tiene efectos tanto en tiempo de compilación como en tiempo de ejecución.

Comentarios

El texto desde un carácter "#" hasta el fin de la línea es un comentario y es ignorado. Excepciones a esto son la inclusión de "#" dentro de una cadena o una expresión regular.

Instrucciones simples

La única clase de instrucción simple que existe es una expresión evaluada por sus efectos colaterales. Cada instrucción simple debe terminarse en un punto y coma excepto si es la última instrucción de un bloque, en cuyo caso el punto y coma es opcional. Sin embargo, ponga el punto y coma de todos modos, si el bloque tiene más de una línea, porque a la larga puede añadir otra línea. Tenga en cuenta que hay operadores como eval {}, sub {}, y do {} que se parecen a sentencias compuestas, pero no lo son -solo son TÉRMINOS en una expresión- y por lo tanto necesita una terminación explícita cuando se usa como el último elemento en una sentencia.

Verdad y Falsedad

El número 0, las cadenas '0' y "", la lista vacía () y undef son todos falsos en contexto booleano. Todos los demás valores son verdadero. La negación del valor de verdadero con ! o not devuelve un valor falso especial. Cuando se evalúa como una cadena se trata como "", pero como número se trata como 0. La mayorí parte de los operadores de Perl que devuelven verdadero o falso se comportan de esta manera.

Modificadores de instrucciones

Cualquier instrucción simple puede ser seguida opcionalmente por un ÚNICO modificador, justo antes del punto y coma final (o del final del bloque). Los posibles modificadores son:

if EXPR
unless EXPR
while EXPR
until EXPR
for LIST
foreach LIST
when EXPR

La EXPR siguiente al modificador es referida como la "condición". Su verdad o falsedad determina cómo se comportará el modificador.

if ejecuta la instrucción una vez si y sólo si la condición es verdadera. unless es el opuesto, ejecuta la instrucción si la condición no es verdadera (es decir, si la condición es falsa).

print "El perro de caza Basset tiene largas orejas" if length $oreja >= 10;
vete_fuera() and juega() unless $este_lloviendo;

El modificador for(each) es un iterador: ejecuta la instrucción una vez por cada elemento en la LISTA (con $_ asociado a cada elemento en cada iteración).

print "Hola $_!\n" for qw(mundo Dolly enfermera);

while repite la instrucción mientras la condición sea cierta. until hace lo opuesto, repite la instrucción hasta que la condición sea verdadera (o mientras la condición sea falsa):

# Estas dos líneas cuentan de 0 a 10.
print $i++ while $i <= 10;
print $j++ until $j >  10;

Los modificadores while y until tienen la usual semántica de los "bucles while" (la condición se evalúa primero), excepto cuando se aplica a un bloque do (o a la subrutina de Perl 4 do), en cuyo caso el bloque se ejecuta una vez antes de que sea evaluada la condición.

De esa manera puede escribir bucles como este:

do {
    $linea = <STDIN>;
    ...
} until !defined($linea) || $linea eq ".\n"

Ver "do" in perlfunc. Note también que las instrucciones de control de bucles descritas más adelante NO funcionarán con esta construcción, porque los modificadores no toman etiquetas de bucle. Lo sentimos. Siempre puede poner otro bloque dentro de él (para next) o alrededor de él (para last) para hacer esta suerte de cosas. Para next, solamente doble las llaves:

do {{
    next if $x == $y;
    # hacer algo aquí
}} until $x++ > $z;

Para last, ha de ser un poco más elegante

BUCLE: {
        do {
            last if $x = $y**2;
            # hacer algo aquí
        } while $x++ <= $z;
}

NOTA: El comportamiento de my, state, o our modificada con una instrucción de modificador condicional o construcción de bucle (por ejemplo, my $x if ...) es indefinido. El valor de la variable my puede ser undef, cualquier valor anteriormente asignado, o posiblemente, cualquier otra cosa. No confíe en él. Futuras versiones de perl pueden hacer algo diferente de la versión de perl que esté probando. A partir de aquí, dragones.

El modificador when es una característica experimental que apareció por primera vez en Perl 5.14. Para usarlo, debe incluir una declaración use v5.14. (Técnicamente, se requiere sólo la característica switch, pero este detalle no estaba disponible antes de 5.14). Solo es operativo desde dentro de un bucle foreach o un bloque given, y se ejecuta la sentencia sólo si es cierta la coincidencia inteligente $_ ~~ EXPR. Si la instrucción se ejecuta, es seguida por un next desde el interior de un foreach y por un break desde el interior de un given.

En la implementación actual, el bucle foreach puede estar en cualquier lugar dentro del ámbito dinámico del modificador when, pero debe estar dentro del ámbito léxico del bloque given. Esta restricción puede ser relajada en una futura versión. Vea a continuación "Instrucciones Switch".

Instrucciones compuestas

En Perl, una secuencia de instrucciones que define un ámbito se llama un bloque. Algunas veces un bloque está delimitado por el archivo que lo contiene (en el caso de un archivo requerido, o el programa entero) y otras veces un bloque está delimitado por la extensión de una cadena (en el caso de un eval).

Pero generalmente, un bloque está delimitado por llaves. Llamaremos a esta construcción sintáctica un BLOQUE.

Las siguientes instrucciones compuestas pueden ser usadas para controlar el flujo:

if (EXPR) BLOQUE
if (EXPR) BLOQUE else BLOQUE
if (EXPR) BLOQUE elsif (EXPR) BLOQUE ...
if (EXPR) BLOQUE elsif (EXPR) BLOQUE ... else BLOQUE

unless (EXPR) BLOQUE
unless (EXPR) BLOQUE else BLOQUE
unless (EXPR) BLOQUE elsif (EXPR) BLOQUE ...
unless (EXPR) BLOQUE elsif (EXPR) BLOQUE ... else BLOQUE

given (EXPR) BLOQUE

ETIQUETA while (EXPR) BLOQUE
ETIQUETA while (EXPR) BLOQUE continue BLOQUE

ETIQUETA until (EXPR) BLOQUE
ETIQUETA until (EXPR) BLOQUE continue BLOQUE

ETIQUETA for (EXPR; EXPR; EXPR) BLOQUE
ETIQUETA for VAR (LISTA) BLOQUE
ETIQUETA for VAR (LISTA) BLOQUE continue BLOQUE

ETIQUETA foreach (EXPR; EXPR; EXPR) BLOQUE
ETIQUETA foreach VAR (LIST) BLOQUE
ETIQUETA foreach VAR (LIST) BLOQUE continue BLOQUE

ETIQUETA BLOQUE
ETIQUETA BLOQUE continue BLOQUE

FASE BLOQUE

La declaración experimental given no se activa automáticamente; vea "Instrucciones Switch" a continuación para saber cómo hacerlo, y las advertencias que le acompañan.

A diferencia del C y Pascal, en Perl están definidas en términos de BLOQUES, no de instrucciones. Esto significa que las llaves son necesarias: no se permiten instrucciones sueltas. Si quiere escribir condicionales sin llaves hay otras formas de hacerlo. Todo lo siguiente hace lo mismo:

if (!open(FOO)) { die "No puedo abrir $FOO: $!" }
die "No se puede abrir $FOO: $!" unless open(FOO);
open(FOO)  || die "No puedo abrir $FOO: $!";
open(FOO) ? () : die "no puedo abrir $FOO: $!";
    # Un poco exótico, este último

La instrucción if es sencilla. Como los BLOQUES están siempre rodeados de llaves, nunca hay ambigüedad sobre dónde van el if y el else. Si usa unless en lugar de if, el sentido del test se invierte. Como if, unless puede ser seguido por else. unless puede, incluso, ser seguido por una o más instrucciones elsif, aunque quizás quiera pensarlo dos veces antes de usar esta construcción del lenguaje tan particular, lo mismo que cualquiera que al leer su código tendrá que pensar al menos dos veces antes de entender qué ha querido decir.

La instrucción while ejecuta el bloque mientras la expresión sea verdadera. La instrucción until ejecuta el bloque mientras la expresión sea falsa. La ETIQUETA es opcional, y si está presente, consiste en un identificador seguido por el carácter dos puntos. La ETIQUETA identifica el bucle para las instrucciones de control de bucle next, last y redo. Si la ETIQUETA se omite, las instrucciones de control de bucle se refieren al bucle más interior en que se encuentren. Esto puede incluir el analizar la pila de llamadas, de forma dinámica, en tiempo real, para encontrar la ETIQUETA. Tal desesperado comportamiento lanzará un aviso si usa el pragma use warnings o la opción -w.

Si existe un BLOQUE continue, siempre es ejecutado justo antes de que la condición sea evaluada de nuevo. Así, puede ser usada para incrementar una variable de bucle, incluso cuando el ciclo ha sido parado por medio de la instrucción next.

Cuando un bloque es precedido por una palabra clave de fase de compilación como BEGIN, END, INIT, CHECK, o UNITCHECK, entonces el bloque se ejecutará solo durante la correspondiente fase de ejecución. Vea perlmod para más detalles.

Hay módulos de extensiones que también pueden engancharse en el intérprete de Perl para definir nuevas clases de instrucciones compuestas. Son presentadas por una palabra clave que la extensión reconoce, y la sintaxis que le sigue se define enteramente por la extensión. Si es usted un implantador, mire "PL_keyword_plugin" in perlapi para informarse sobre este mecanismo. Si está usando un módulo así, mire la documentación del módulo para ver los detalles de la sintaxis que define.

Control de bucles

El comando next inicia la siguiente iteración del bucle:

LINEA: while (<STDIN>) {
    next LINEA if /^#/;     # descartar comentarios
    ...
}

El comando last sale inmediatamente del bucle en cuestión. El bloque continue, si está, no se ejecuta:

LINEA: while (<STDIN>) {
    last LINE if /^$/;      # salir cuando se termine la cabecera
    ...
}

El comando redo reinicia la iteración sin evaluar de nuevo la condición. El bloque continue, si está presente, no se ejecuta. Este comando se usa, normalmente, por los programas que quieren engañarse a sí mismos sobre lo que fue introducido.

Por ejemplo, cuando se procesa un archivo como /etc/termcap. Si las líneas de entrada acaban en barras diagonales inversas para indicar continuación, querrá saltarlo y obtener el siguiente registro.

while (<>) {
    chomp;
    if (s/\\$//) {
        $_ .= <>;
        redo unless eof();
    }
    # ahora se procesa $_
}

que es la forma corta que tiene Perl de la siguiente versión escrita de manera más explícita:

LINEA: while (defined($linea = <ARGV>)) {
    chomp($linea);
    if ($linea =~ s/\\$//) {
        $linea .= <ARGV>;
        redo LINEA unless eof(); # ¡no es eof(ARGV)!
    }
    # ahora, procesa $linea
}

Note que si existiese un bloque continue en este código, sería ejecutado sólo en las líneas descartadas por la expresión regular (debido a que redo salta el bloque continue). Un bloque continue se usa a menudo para reiniciar contadores de línea o patrones m?patrón? de un sólo uso:

# inspirado por :1,$g/fred/s//WILMA/
while (<>) {
    m?(fred)?    && s//WILMA $1 WILMA/;
    m?(barney)?    && s//BETTY $1 BETTY/;
    m?(homer)?   && s//MARGE $1 MARGE/;
} continue {
    print "$ARGV $.: $_";
    close ARGV if eof;              # reinicia $.
    reset       if eof;             # reinicia ?patrón?
}

Si la palabra while se reemplaza por la palabra until, el sentido del test se invierte, pero la condición es comprobada siempre antes de la primera iteración.

Las instrucciones de control de bucle no funcionan en un if o unless, porque no son bucles. Aunque puede doblar las llaves para crearlos.

if (/patrón/) {{
    last if /pedro/;
    next if /pablo/;  # mismo efecto que "last",
                      # pero es menos claro
    # hacer algo aquí
}}

Esto funciona así por el hecho de que un bloque, por sí mismo, actúa como un bucle que se ejecuta una sola vez. Ver "BLOQUES básicos".

La forma while/if BLOQUE BLOQUE, existente en Perl 4, ya no está disponible. Reemplace cada ocurrencia de if BLOQUE por if (do BLOQUE).

Bucles for

El estilo de los bucles for del C funcionan igual que el correspondiente bucle while. Es decir:

for ($i = 1; $i < 10; $i++) {
    ...
}

es lo mismo que:

$i = 1;
while ($i < 10) {
    ...
} continue {
    $i++;
}

Hay una pequeña diferencia: si hay variables declaradas con my en la sección de inicialización del for, el ámbito léxico de estas variables es exactamente el bucle for (el cuerpo del bucle y las secciones de control).

Como un caso especial, si el test en el bucle for (o el correspondiente bucle while) está vacío, se trata como verdadero. Es decir, tanto

for (;;) {
    ...
}

y

while () {
    ...
}

se tratan como bucles infinitos.

Además de recorrer los índices de los arrays, for puede prestarse a otras interesantes aplicaciones. Aquí hay una que evita el problema, al comprobar explícitamente, por el fin de archivo en un descriptor de archivo interactivo, que parezca que su programa se haya quedado colgado.

$en_un_tty = -t STDIN && -t STDOUT;
sub prompt { print "¿si? " if $en_un_tty }
for ( prompt(); <STDIN>; prompt() ) {
    # hacer algo
}

Usando readline (o el operador <EXPR>) como condición de un bucle for, es una forma abreviada de escribir lo siguiente. Este comportamiento es el mismo que en la condición de un bucle while.

for ( prompt(); defined( $_ = <STDIN> ); prompt() ) {
    # hacer algo
}

Bucles foreach

El bucle foreach itera sobre los valores de una lista normal y pone la variable escalar VAR a cada uno de los elementos de la lista. Si la variable es precedida por la palabra clave my, entonces su ámbito es léxicamente local y por eso es visible sólo dentro del bucle. Dicho de otra forma, la variable es implícitamente local al bucle y recupera su valor anterior al salir del bucle. Si la variable fue previamente declarada con my, usará esta variable en vez de la global, pero sigue siendo local en el bucle. Esta implícita localización ocurre solamente en un bucle foreach.

En realidad, la palabra clave foreach es un sinónimo de la palabra clave for, por lo que puede usar cualquiera de las dos. Si se omite VAR, se le asigna cada valor a $_.

Si cualquier elemento de LISTA es un valor-izquierda, puede modificarlo, modificando VAR dentro del bucle. Recíprocamente, si cualquier elemento de LISTA NO es un valor-izquierda, cualquier intento de modificar este elemento fallará (provocará un error). En otras palabras, la variable índice del bucle foreach es implícitamente un alias de cada elemento de la lista sobre la que está iterando.

Si cualquier parte de la LISTA es un array, foreach quedará confundido si añade o quita elementos dentro del cuerpo del bucle, por ejemplo, al usar splice. Así que no lo haga.

foreach probablemente no hará lo esperado si VAR está atada a otra variable especial. Tampoco haga esto.

A partir de Perl 5.22, hay un variante experimental de este bucle que acepta a una variable precedida por una barra diagonal inversa para VAR, en cuyo caso los elementos en la LISTA deben ser referencias. La variable escapada con la barra diagonal inversa se convertirá en un alias de cada elemento referenciado en la LISTA, que deberán ser del tipo correcto. La variable no necesita ser un escalar en este caso, y la barra diagonal inversa puede preceder a my. Para usar esta forma, debe activar la característica refaliasing a través de use feature. (Vea feature. Vea también "Asignación a referencias" in perlref).

Ejemplos:

for (@array) { s/foo/bar/ }

for my $elem (@elementos) {
    $elemento *= 2;
}

for $cuenta (reverse(1..10), "BOOM") {
    print $cuenta, "\n";
    sleep(1);
}

for (1..15) { print "Feliz Navidad\n"; }

foreach $item (split(/:[\\\n:]*/, $ENV{TERMCAP})) {
    print "Item: $item\n";
}

use feature "refaliasing";
no warnings "experimental::refaliasing";
foreach \my %hash (@array_de_referencias_a_hash) {
    # hacer algo con cada %hash
}

Aquí hay un ejemplo de cómo un programador de C codificaría un determinado algoritmo en Perl:

for (my $i = 0; $i < @array1; $i++) {
    for (my $j = 0; $j < @ary2; $j++) {
        if ($ary1[$i] > $ary2[$j]) {
            last; # no puedo volver al bucle más externo :-(
        }
        $ary1[$i] += $ary2[$j];
    }
    # Aquí es donde lleva el 'last'
}

Y aquí está cómo un programador de Perl, más cómodo con el lenguaje, puede hacer:

EXTERNO: for my $wid (@array1) {
INTERNO:   for my $jet (@ary2) {
            next EXTERNO if $wid > $jet;
            $wid += $jet;
         }
      }

¿Ha visto que es mucho más fácil? Es más limpio, seguro y rápido. Es más limpio porque es menos ruidoso. Es más seguro porque si se añade nuevo código entre los bucles interno y externo, ese nuevo código no será ejecutado accidentalmente. El next explícitamente itera sobre el otro bucle en vez de meramente terminar el interno. Y es más rápido porque Perl ejecuta una instrucción foreach más rápidamente que su equivalente en un bucle for.

Hackers Perl perspicaces pueden haber notado que un bucle for tiene un valor de retorno, y ese valor puede capturarse envolviendo el bucle en un bloque do. La recompensa de este descubrimiento es una advertencia en forma de consejo: El valor de retorno de un bucle for no está especificado y puede cambiar sin previo aviso. No confíe en él.

BLOQUES básicos

Un BLOQUE por sí mismo (etiquetado o no) es semánticamente equivalente a un bucle que se ejecuta una vez. Así que puede usar cualquiera de las instrucciones de control de bucle dentro de él para salir o reiniciarlo. (Note que esto NO es verdad en eval{}, sub{}, y contrariamente a la creencia popular, bloques do{}, que NO cuentan como bucles). El bloque continue es opcional.

La construcción BLOQUE puede ser usada para emular estructuras switch.

SWITCH: {
    if (/^abc/) { $abc = 1; last SWITCH; }
    if (/^def/) { $def = 1; last SWITCH; }
    if (/^xyz/) { $xyz = 1; last SWITCH; }
    $nada = 1;
}

También encontrará que el bucle foreach se utiliza para crear un actualizador y un switch:

SWITCH:
for ($var) {
    if (/^abc/) { $abc = 1; last SWITCH; }
    if (/^def/) { $def = 1; last SWITCH; }
    if (/^xyz/) { $xyz = 1; last SWITCH; }
    $nada = 1;
}

Estas construcciones son muy frecuentes, porque las versiones anteriores de Perl no tenían oficialmente una instrucción switch, y también porque la nueva versión descrita inmediatamente a continuación sigue siendo experimental, y algunas veces puede confundir.

Instrucciones Switch

A partir de Perl 5.10 (bueno, 5.10.0, pero no funciona bien), puede decir

use feature "switch";

para habilitar la característica experimental switch. Esto se basa de forma libre en una versión antigua de una propuesta para Perl 6, pero ya no se asemeja a la construcción de Perl 6. También obtendrá la característica switch cada vez que declare que su código prefiere ejecutarse en una versión de Perl que sea 5.10 o posterior. Por ejemplo:

use v5.14;

Con la característica "switch", Perl gana las palabras clave given, when, default, continue, y break. A partir de Perl 5.16, se puede cambiar el prefijo de las palabras clave con CORE:: para acceder a las nuevas características sin tener que usar una declaración use feature. Las palabras clave given y when son análogos a switch y case en otros lenguajes, por lo que la sección anterior podría ser reescrita como

use v5.10.1;
for ($var) {
    when (/^abc/) { $abc = 1 }
    when (/^def/) { $def = 1 }
    when (/^xyz/) { $xyz = 1 }
    default       { $nada = 1 }
}

El foreach es la forma no experimental de crear un actualizador. Si desea utilizar el, altamente experimental, given, se podría escribir de esta manera:

use v5.10.1;
given ($var) {
    when (/^abc/) { $abc = 1 }
    when (/^def/) { $def = 1 }
    when (/^xyz/) { $xyz = 1 }
    default       { $nada = 1 }
}

A partir de 5.14, también se puede escribir de esta manera:

use v5.14;
for ($var) {
    $abc = 1 when /^abc/;
    $def = 1 when /^def/;
    $xyz = 1 when /^xyz/;
    default { $nada = 1 }
}

O si no le importa arriesgarse, de esta manera:

use v5.14;
given ($var) {
    $abc = 1 when /^abc/;
    $def = 1 when /^def/;
    $xyz = 1 when /^xyz/;
    default { $nada = 1 }
}

Los argumentos de given y when están en contexto escalar, y given asigna a la variable $_ el valor de su argumento.

Lo que el argumento EXPR hace en when es difícil de describir con precisión, pero en general, trata de adivinar lo que quiere hacer. A veces se interpreta como $_ ~~ EXPR, y a veces no. También se comporta de forma diferente cuando está léxicamente encerrada por un bloque given que cuando está dinámicamente encerrada por un bucle foreach. Las reglas son demasiado difíciles de entender como para describirlas aquí. Vea "Detalles experimentales en given y when", más adelante.

Debido a un desafortunado error en la forma en que se implementó given entre Perl 5.10 y 5.16, la versión de $_ gobernada por given no es más que una copia léxica contextualizada del original, no un alias dinámicamente contextualizado del original, como lo sería si se tratara de un foreach o del original de la actual especificación del lenguaje Perl 6. Este error fue corregido en Perl 5.18. Si quiere, realmente, tener una $_ léxica, especifíquelo explícitamente, pero note que my $_ es obsoleto y lanzará una advertencia a menos que las advertencias estén desactivadas:

given(my $_ = EXPR) { ... }

Si su código sigue necesitando ejecutarse en versiones anteriores, únase a foreach como su actualizador y será más feliz.

Goto

Aunque no sea muy querido, Perl soporta la instrucción goto. Existen tres formas: goto-ETIQUETA, goto-EXPR y goto-&NOMBRE. La ETIQUETA de un bucle no es realmente un destino válido para un goto; sólo es el nombre del bucle.

La forma goto-ETIQUETA busca la instrucción etiquetada con ETIQUETA y continua la ejecución desde allí. No puede ser usado en ninguna construcción que requiera inicialización, como una subrutina o un bucle foreach. Tampoco puede ir en una construcción que sea optimizada. Puede ser utilizada para ir a casi cualquier sitio que esté dentro del ámbito dinámico, incluyendo fuera de las subrutinas, pero es normalmente mucho mejor otras construcciones como last o die. El autor de Perl nunca ha sentido la necesidad de usar esta forma de goto (en Perl, desde luego. C es otra historia).

La forma goto-EXPR espera un nombre de etiqueta, cuyo ámbito será resuelto dinámicamente. Esto permite crear goto calculados como en FORTRAN, pero no está necesariamente recomendado si usted está optimizando, durante el mantenimiento:

goto(("FOO", "BAR", "GLARCH")[$i]);

La forma goto-&NOMBRE es muy mágica, y sustituye a una llamada a una subrutina con nombre desde la actual subrutina que se está ejecutando. Esto se usa por subrutinas AUTOLOAD() que desean cargar otra subrutina y fingen que ésta otra subrutina ha sido llamada en primer lugar (excepto que cualquier modificación a @_ en la subrutina actual se propaga a la otra). Después del goto, ni siquiera caller() será capaz de decir qué rutina fue llamada en primer lugar.

En casi todos los casos como este, es usualmente una mejor, mucho mejor idea, usar los mecanismos de control de flujo de next, last o redo en vez de recurrir a goto. Para ciertas aplicaciones, la pareja eval{} y die() puede ser un prudente planteamiento para el procesamiento de excepciones.

La instrucción elipsis

A partir de Perl 5.12, Perl acepta los puntos suspensivos (elipsis), "...", como un marcador de posición para el código que aún no ha implementado. Esta forma de elipsis, la instrucción no implementada, no debe confundirse con el operador binario flip-flop .... El primero es una instrucción y el otro es un operador. (Perl no suele confundirlos, porque, por lo general, Perl puede decidir si espera un operador o una instrucción, pero vea a continuación las excepciones).

Cuando Perl 5.12 o posterior encuentra una elipsis, lo analiza como si no tuviera errores, pero siempre y cuando lo trate realmente de ejecutar, Perl produce una excepción con el texto Unimplemented (No implementado):

use v5.12;
sub no_implementado { ... }
eval { no_implementado() };
if ($@ =~ /^Unimplemented at /) {
    say "¡Encontré una elipsis!";
}

Sólo puede utilizar la instrucción elipsis para sustituir a una instrucción completa. Estos ejemplos muestran cómo funciona la elipsis:

use v5.12;
{ ... }
sub foo { ... }
...;
eval { ... };
sub algodeazucar {
    my $self = shift;
    ...;
}
$x = do {
    my $n;
    ...;
    say "¡Hurra!";
    $n;
};

La instrucción elipsis no puede estar en una expresión que forma parte de una instrucción mayor, ya que el ... es también la versión de tres puntos del operador flip-flop (vea "Operadores rango" in perlop).

Estos ejemplos de intentos de utilizar la elipsis son errores de sintaxis:

use v5.12;

print ...;
open(my $fh, ">", "/dev/passwd") or ...;
if ($condicion && ... ) { say "¡Hola!" };

Hay algunos casos donde Perl no puede decir, de forma inmediata, la diferencia entre una expresión y una instrucción. Por ejemplo, la sintaxis para un bloque y un constructor de referencia a un hash anónimo tienen el mismo aspecto a menos que haya algo dentro de las llaves que le den una pista a Perl. La elipsis es un error de sintaxis si Perl no adivina que { ... } es un bloque. En ese caso, no cree que ... sea una elipsis porque está esperando una expresión en lugar de una instrucción:

@transformado = map { ... } @entrada; # error de sintaxis

Dentro de su bloque, puede usar un ; antes de la elipsis denotar que { ... } es un bloque y no una referencia a un constructor hash. Ahora la elipsis funciona:

@transformado = map {; ... } @entrada;   # ';' deshace la ambigüedad

Nota: Algunas personas se refieren coloquialmente a este trozo de caracteres de puntuación como un "blablablá" o "tres puntos seguidos", pero su verdadero nombre es en realidad elipsis.

POD: Documentación embebida

Perl tiene un mecanismo para entremezclar documentación y código fuente. Mientras que él espera el comienzo de una nueva instrucción, si el compilador encuentra una línea que comienza con un signo de igual y una palabra, como esta:

=head1 ¡Aquí estarán los Pods!

Entonces este texto y el siguiente hasta incluir una línea que comience por =cut será ignorada. El formato del texto intermedio está descrito en perlpod.

Esto le permite entremezclar código fuente y texto de la documentación libremente, como por ejemplo

=item snazzle($)

La función snazzle() se convertirá en la más espectacular
forma que pueda posiblemente imaginar, incluyendo
pirotecnia cibernética.

=cut devuelta al compilador, ¡lejos de este material pod!

sub snazzle($) {
    my $cosita = shift;
    .........
}

Note que los traductores pod suelen mirar sólo en los párrafos que comiencen por una directiva pod (hace el parseo más fácil), mientras que el compilador realmente sabe mirar por las secuencias pod incluso en el medio de un párrafo. Esto significa que el siguiente material secreto será ignorado tanto por el compilador como por los traductores.

$a=3;
=material secreto
 warn "Ni POD ni CÓDIGO!?"
=cut back
print "tengo $a\n";

Probablemente no se dará cuenta de que el warn() ha sido comentado para siempre. No todos los traductores pod están bien entrenados a este respecto y quizá el compilador sea más quisquilloso.

Uno puede también usar directivas pod para comentar, de forma rápida, una sección de código.

Comentarios sencillos y viejos (¡No!)

Perl puede procesar directivas como lo hace el preprocesador de C. Usando esto, uno puede controlar la idea que tiene Perl de los nombres de archivos y número de líneas en los mensajes de avisos y errores (especialmente para las cadenas procesadas con eval()). La sintaxis de este mecanismo es el mismo que para la mayoría de preprocesadores de C: coincide con la expresión regular

# ejemplo: '# line 42 "nuevo_archivo.plx"'
/^\#   \s*
  line \s+ (\d+)   \s*
  (?:\s("?)([^"]+)\g2)? \s*
 $/x

con $1 siendo el número de línea para la línea siguiente y $3 siendo el nombre de archivo opcional (especificado con o sin comillas). Tenga en cuenta que no puede haber espacios en blanco delante de #, a diferencia de preprocesadores C modernos.

Existe obviamente un problema con esta directiva: los debuggers y perfiladores sólo mostrarán la última línea del código fuente que aparece en un número de línea en particular de un determinado archivo. Hay que tener cuidado para no causar colisiones de números de línea en el código que pretenda depurar más tarde.

Aquí hay algunos ejemplos que será capaz de escribir en la línea de comandos del shell:

% perl
# line 200 "bzzzt"
# el '#' en la línea anterior debe ser el primer carácter de la línea
die 'foo';
__END__
foo at bzzzt line 201.

% perl
# line 200 "bzzzt"
eval qq[\n#line 2001 ""\ndie 'foo']; print $@;
__END__
foo at - line 2001.

% perl
eval qq[\n#line 200 "foo bar"\ndie 'foo']; print $@;
__END__
foo at foo bar line 200.

% perl
# line 345 "goop"
eval "\n#line " . __LINE__ . ' "' . __FILE__ ."\"\ndie 'foo'";
print $@;
__END__
foo at goop line 345.

Detalles experimentales en given y when

Como se mencionó anteriormente, la característica "switch" está considerada como altamente experimental; está sujeta a cambios sin previo aviso. En particular, when tienen comportamientos complicados, de los que se espera que cambien en el futuro, para que sean menos complicados. No confíe en sus actuales (y malas) implementaciones. Antes de Perl 5.18, given también tiene comportamientos complicados de los que debería estar atento si su código debe ejecutarse en versiones anteriores de Perl.

He aquí un ejemplo más largo de given:

use feature ":5.10";
given ($foo) {
    when (undef) {
        say '$foo es indefinido';
    }
    when ("foo") {
        say '$foo es la cadena "foo"';
    }
    when ([1,3,5,7,9]) {
        say '$foo es un dígito impar';
        continue; # Sigue en la siguiente
    }
    when ($_ < 100) {
        say '$foo es numéricamente menor que 100';
    }
    when (\&confirmacion_complicada) {
        say 'una confirmación complicada para $foo es cierta';
    }
    default {
        die q(No sé qué hacer con $foo);
    }
}

Antes de Perl 5.18, given(EXPR) asignaba el valor de EXPR a una copia (!) de ámbito léxico de $_, no un alias dinámicamente contextualizado de la forma que foreach hace. Eso hace que sea similar a

do { my $_ = EXPR; ... }

excepto que el bloque es, automáticamente, detenido, por un when con éxito o un explícito break. Debido a que era sólo una copia, y porque sólo estaba léxicamente contextualizada, no puede realizar las mismas cosas que podría hacer en un bucle foreach. En particular, no funciona para llamadas arbitrarias a funciones si estas funciones intentan acceder a $_. Para eso, es mejor que apueste por foreach.

La mayor parte del poder viene de la coincidencia inteligente implícita que puede aplicar en algunas situaciones. En la mayor parte de los casos, when(EXPR) se trata como una coincidencia inteligente implícita de $_, es decir, $_ ~~ EXPR. (Vea "Operador coincidencia inteligente" in perlop para más información sobre coincidencia inteligente). Pero cuando EXPR es una de los 10 casos excepcionales (o cosas como éstas) que se enumeran a continuación, se utiliza directamente como valor booleano.

1.

Una llamada a una subrutina definida por el usuario o una invocación de método.

2.

Una expresión regular en la forma de /REGEX/, $foo =~ /REGEX/ o $foo =~ EXPR. También, una expresión regular negada en la forma de !/REGEX/, $foo !~ /REGEX/ o $foo !~ EXPR.

3.

Una coincidencia inteligente que utilice un operador explícito ~~, como por ejemplo EXPR ~~ EXPR.

NOTA: A menudo se tiene que usar $c ~~ $_ porque la prueba por defecto es $_ ~~ $c, que es frecuentemente lo opuesto a lo que se desea.

4.

Un operador de comparación booleano como $_ < 10 o $x eq "abc". Los operadores relacionales que se aplican aquí son los seis comparadores numéricos (<, >, <=, >=, == y !=) y los seis operadores de cadena (lt, gt, le, ge, eq y ne).

5.

Por lo menos, las tres funciones predefinidas defined(...), exists(...) y eof(...). Algún día podríamos agregar más de estos casos, más adelante, si pensamos en ellos.

6.

una expresión negada, tanto !(...) o not (...), o un exclusivo-or lógico (...) xor (...). Las versiones a nivel de bits (~ y ^) no están incluidas.

7.

Un operador de test de archivo, con exactamente 4 excepciones: -s, -M, -A y -C, que devuelven valores numéricos, no booleanos. El operador de test de archivo -z no está incluido en la lista de excepciones.

8.

Los operadores biestables .. y .... Tenga en cuenta que el operador biestable ... es completamente distinto de la instrucción elipsis ... descrita antes.

En los 8 casos anteriores, el valor de EXPR se utiliza directamente como un valor booleano, por lo que no se hace coincidencia inteligente. Puede pensar en when como una coincidencia inteligente más inteligente.

Además, Perl inspecciona los operandos de los operadores lógicos para decidir si se debe usar coincidencia inteligente para cada uno de ellos mediante la aplicación de la prueba anterior a los operandos:

9.

Si EXPR es EXPR1 && EXPR2 o EXPR1 and EXPR2, el test se aplica recursivamente a ambas EXPR1 y EXPR2. Sólo si ambos operandos también pasan la prueba, recursivamente, la expresión será tratada como booleana. De lo contrario, se utiliza coincidencia inteligente.

10.

Si EXPR es EXPR1 || EXPR2, EXPR1 // EXPR2 o EXPR1 or EXPR2, el test se aplica recursivamente a solo EXPR1 (que puede ser a la vez un operador AND de mayor precedencia, por ejemplo, y por lo tanto sujeto a la regla anterior), no a EXPR2. Si EXPR1 va a utilizar coincidencia inteligente, entonces EXPR2 también lo hace, sin importar lo que contenga EXPR2. Pero si EXPR2 no llega a utilizar coincidencia inteligente, entonces el segundo argumento tampoco lo hará. Esto es muy diferente del caso && descrito antes, así que tenga cuidado.

Estas reglas son complicadas, pero el objetivo es que hagan lo que usted desea (aunque no entienda muy bien por qué lo están haciendo). Por ejemplo:

when (/^\d+$/ && $_ < 75) { ... }

será tratado como una coincidencia booleana porque las reglas dicen que tanto una expresión regular de una coincidencia y una prueba explícita sobre $_ serán tratados como booleanos.

También:

when ([qw(foo bar)] && /baz/) { ... }

usará coincidencia inteligente porque sólo uno de los operandos es un valor booleano: el otro utiliza coincidencia inteligente, y así funciona.

Además:

when ([qw(foo bar)] || /^baz/) { ... }

usará coincidencia inteligente (sólo el primer operando es considerado), mientras que

when (/^baz/ || [qw(foo bar)]) { ... }

pondrá a prueba sólo la expresión regular, lo que hace que ambos operandos sean tratados como booleanos. Tenga cuidado con esto, porque una referencia a un array es siempre un valor verdadero, lo que, efectivamente, es redundante. No es una buena idea.

Los operadores booleanos tautológicos siguen teniendo que ser optimizados. No caiga en la tentación de escribir

when ("foo" or "bar") { ... }

Esto quedará optimizado en "foo", así que "bar" nunca será considerado (incluso aunque las reglas digan que hay que usar coincidencia inteligente en "foo"). Para una alternativa como ésta, una referencia a un array funcionará, porque esto lanzará la coincidencia inteligente:

when ([qw(foo bar)] { ... }

Esto es algo equivalente a la funcionalidad de la instrucción switch del C (no debe confundirse con la funcionalidad de Perl; vea más adelante), en donde el mismo bloque se utiliza para varias instrucciones case.

Otro método abreviado útil es que, si usa un literal array o hash, como argumento a given, se convierte en una referencia. Asi que given(@foo) es lo mismo que given(\@foo).

default se comporta exactamente igual que when(1 == 1), que es lo mismo que decir que siempre coincide.

Saliendo

Puede usar la palabra clave break para salir del bloque given actual. Cada bloque when se termina, implícitamente, con un break.

Atravesar

Puede usar la palabra clave continue para pasar de un caso al siguiente:

given($foo) {
    when (/x/) { say '$foo contiene una x'; continue }
    when (/y/) { say '$foo contiene una y'          }
    default    { say '$foo no contiene una y'       }
}

Valor de retorno

Cuando una instrucción given es también una expresión válida (por ejemplo, cuando es la última instrucción de un bloque), se evalúa a:

  • Una lista vacía tan pronto como se encuentre un break explícito.

  • El valor de la última expresión evaluada de la exitosa cláusula when/default, si existe alguna.

  • El valor de la última expresión evaluada del bloque given si ninguna condición es verdadera.

En los dos últimos casos, la última expresión se evalúa en el contexto en el que se aplicó al bloque given.

Tenga en cuenta que, a diferencia de if y unless, las instrucciones fallidas de when siempre se evalúan a una lista vacía.

my $precio = do {
    given ($item) {
        when (["pera", "manzana"]) { 1 }
        break when "voto";      # Mi voto no puede ser comprado
        1e10  when /Mona Lisa/;
        "desconocido";
    }
};

En la actualidad, los bloques given no siempre se pueden utilizar como expresiones individuales. Esto podría cambiarse en una futura versión de perl.

Conmutando en un bucle

En lugar de usar given(), puede usar un bucle foreach(). Por ejemplo, aquí hay una manera de contar cuántas veces aparece una cadena particular en un array:

use v5.10.1;
my $cuenta = 0;
for (@array) {
    when ("foo") { ++$cuenta }
}
print "\@array contiene $cuenta copias de 'foo'\n";

O en una versión más reciente:

use v5.14;
my $cuenta = 0;
for (@array) {
    ++$cuenta when "foo";
}
print "\@array contiene $cuenta copias de 'foo'\n";

Al final de todos los bloques when, hay una instrucción next implícita. Puede invalidarlo con un explícito last si está interesado sólo en la primera coincidencia.

Esto no funciona si especifica explícitamente una variable de bucle, como en for $item (@array). Tiene que usar la variable por defecto $_.

Diferencias con Perl 6

La coincidencia inteligente de Perl 5 y las construcciones given/when no son compatibles con sus análogas en Perl 6. La diferencia más visible y menos importante es que, en Perl 5, los paréntesis son requeridos alrededor del argumento en given() y when() (excepto cuando éste último se usa como modificador de instrucciones). Los paréntesis en Perl 6 son siempre opcionales en las construcciones de control, como en if(), while(), o when(); no pueden ser opcionales en Perl 5, sin ganar una gran confusión, porque Perl 5 interpretaría la expresión

given $foo {
    ...
}

como si el argumento a given fuera un elemento del hash %foo, interpretando las llaves como la sintaxis de un elemento de un hash.

Sin embargo, existen muchas, muchas diferencias. Por ejemplo, esto funciona en Perl 5:

use v5.12;
my @primario = ("rojo", "azul", "verde");

if (@primario ~~ "rojo") {
    say "primario coincide inteligentemente con rojo";
}

if ("rojo" ~~ @primario) {
    say "rojo coincide inteligentemente con primario";
}

say "¡Eso es todo, amigos!";

Pero no funciona en absoluto en Perl 6. En su lugar, debe utilizar en su lugar el (paralelizable) operador any:

if any(@primario) eq "rojo" {
    say "primario coincide inteligentemente con rojo";
}

if "rojo" eq any(@primario) {
    say "rojo coincide inteligentemente con primario";
}

La tabla de coincidencias inteligentes en "Operador coincidencia inteligente" in perlop no es idéntica a la propuesta por la especificación Perl 6, principalmente debido a las diferencias entre los modelos de datos entre Perl 6 y Perl 5 pero también porque la especificación Perl 6 ha cambiado desde que Perl 5 se precipitó en adoptarlo.

En Perl 6, when() siempre hará una coincidencia inteligente implícita con sus argumentos, mientras que en Perl 5 es conveniente (aunque potencialmente confuso) suprimir esta implícita coincidencia inteligente en ciertas y variadas situaciones poco definidas, como se ha documentado anteriormente. (La diferencia es incluso mayor porque Perl 5 no tiene, incluso internamente, un tipo booleano).

POD ERRORS

Hey! The above document had some coding errors, which are explained below:

Around line 6:

Non-ASCII character seen before =encoding in 'DESCRIPCIÓN'. Assuming UTF-8