Creative Commons License
Excepto donde se indique otra cosa, todo el contenido de este lugar está bajo una licencia de Creative Commons.
Taquiones > perl > Novedades en Perl 5.10

Novedades en Perl 5.10

Con la aparición de la versión 5.10 del lenguaje Perl se incluyen unas cuentas novedades muy interesantes, muchas de ellas procedentes del trabajo en Perl 6, que ya pueden utilizarse en su mayoría en la versión 5.9.4.

Para usar las nuevas características se ha añadido una directiva llamada feature; además, como todas ellas tienen ámbito léxico, pueden ser activadas y desactivadas a voluntad.

Como aparecen nuevas palabras reservadas en el lenguaje es necesario habilitar su uso mediante la directiva feature de forma similar a:

use feature qw(err ~~);

Nota: los apuntes aquí mencionados están tomados de fuentes creo que bastante fiables, pero yo no puedo comentar nada a nivel personal porque no los he usado todavía.

defined-or //

Este nuevo operador toma dos expresiones y si la de la izquierda está definida usa su valor; en caso contrario utiliza la expresión derecha.

$izquierda // $derecha;

que es equivalente a

defined $izquierda ? $izquierda : $derecha

Al parecer es bastante común el uso de expresiones como

$a = $valor1 || $valor2;
$b ||= 1;

para asegurarse de que una variable toma un valor concreto cuando falla el primero. El problema se encuentra cuando la primera expresión tiene un valor, pero éste evalúa lógicamente a falso debido a que es uno de estos: 0, '0' ó ''; en este caso debemos comprobar explícitamente si el valor está definido en lugar de evaluarlo lógicamente.

Al igual que los operadores || y && tienen equivalentes de menor prioridad en las figuras de or y and respectivamente, el operador // también tiene su correspondencia de baja prioridad denominada err.

$a = ( $b err $c );

say

say "Hola a todos";

Esta nueva función envuelve al print de siempre y añade un salto de línea al final de sus parámetros:

sub say {
    print @_,"\n_";
}

Es más una ayuda para escribir menos y más deprisa, y evitar errores tontos con el salto de línea.

smart match ~~

El operador smart-match es una versátil herramienta de comparación que puede determinar mágicamente cómo comparar dos elementos.

use feature qw(~~ say);

if ($x ~~ @array) { say "$x está en la lista" }
if ($x ~~ /coco/) { say "coco está en el texto" }
if (@x ~~ /coco/) { say "coco está en la lista" }
if ($key ~~ %hash) { say "$key existe en el hash" }
if ($code_ref ~~ $arg) { say '$code_ref->($arg) return true' }

Es decir:

  • Si se le pasa una lista y un escalar, efectúa una búsqueda de este último dentro del primero.
  • Si se le pasa un patrón de búsqueda lo hace coincidir con el escalar ó la lista que está en el otro lado.
  • Si se le pasa un hash y un escalar usa la función exist para comprobar que esté dentro.
  • Si recibe una referencia a código y un parámetro, efectúa una llamada a dicho código, con dicho parámetro y comprueba que el resultado sea verdadero (sospecho que debo haberme perdido algo porque no entiendo bien la utilidad de ésto).

Este operador puede ser sobrecargado, como cualquier otro, y eso es algo que puede ser interesante en OOP también.

given-when

Este duo es la respuesta de Perl al operador switch de otros lenguajes; sustituye al módulo Switch, que está basado en un filtro de código fuente y no siempre ha funcionado correctamente, especialmente con el depurador.

use feature qw(say switch);

my $var = get_some_value();

given ( $var ) {
    when ( /\D/ ) { say "Tiene que ser un número" }
    when ( $_ == 1 ) { say "Es el uno" }
    default { say "Es el número $_" }
}

given almacena el valor de su argumento en la variable $_ automáticamente. Tras eso Perl evalúa los bloques when hasta que evalúa uno a verdadero, lo ejecuta y termina; en caso de no encontrar ninguno, obviamente, ejecuta el bloque default si existe.

Ya que when utiliza el operador smart-match automáticamente es posible simplificar bastante las comparaciones, por lo que podríamos ampliar el ejemplo anterior con una búsqueda de números en una lista:

my @no_validos = ( 3, 6, 7, 9 );
my @repetidos = ();

given ( $var ) {
    when ( /\D/ ) { say "Tiene que ser un número" }
    when ( @repetidos ) { say "Este número está repetido " }
    when ( @no_validos ) { say "Este número está maldito" }
    when ( $_ == 1 ) { say "Es el uno" }
    default { 
        say "Es el número $_";
        push(@repetidos);
        }
}

foreach-when

La claúsula when también funciona muy bien con foreach puesto que emite un next al terminar su bloque de código.

foreach (@lista_variada_de_cosas) {
    when (/\w+/) { say "me vale como palabra" }
    when (/\d+/) { say "me vale como número " }
}

directivas léxicas definidas por el usuario

FIXME

variables persistentes

Las variables persistentes (ó de estado) almacenan información entre las distintas llamadas a una función. La forma de conseguir este tipo de variables en la actualidad es con variables léxicas, confinadas dentro de un bloque y un función como en

{
    my $accum = 0;

    sub add_value {
        $accum += shift;

        return $accum;
    }
}

El nuevo cualificador state permite simplificar la síntaxis a:

use feature qw(state);

sub add_value {
    state $accum = 0;

    return $accum += shift;
}

parámetro -E

Este nuevo parámetro de llamada del intérprete Perl permite utilizar estas nuevas características sin necesidad de importarlas explícitamente dentro del módulo:

$ perl -E ' say "esto funciona" '

Habilita todas las nuevas posibilidades de la directiva feature, y puede usarse de la forma tradicional también:

$ perl -e ' use feature qw(say);  say "esto funciona" ' 
$ perl -Mfeature=say -e ' say "esto funciona" '

constant folding

FIXME

UNIVERSAL::DOES

Dado que aún no tengo información práctica sobre esta nueva función, mejor copio el párrafo original que encontré por si a alguien le da alguna pista y, de paso, puede enseñarme algo, que estoy un poco perdido:

UNIVERSAL::DOES is like isa, bu it doesn't depend on an inheritance relationship. I can check a class or an object to find out it behaves in a certain way, which Perl 5.10 call roles. A role is a grouping of special behaviors, mostly through method names i can call.

DOES is similar as isa, since i know that if it returns true the the object or class has a certain method even outside its @ISA tree, while DOES does not worry about it where this method comes from.

Otras mejoras

La siguiente es una lista de mejoras y cambios de los que aún no tengo mucha información:

  • Expresiones regulares más rápidas
  • Mejor soporte de UTF-8
  • Menor consumo de memoria
  • Hashes de campos (field hashes)
  • Aseveraciones (assertions)
  • $AUTOLOAD se marca como tainted si el nombre del método también lo está.
  • Los filtros de código fuente pueden aplicarse también al array @INC
  • Gestión de hilos mejorada
  • Más mejoras para Windows
  • Más documentación

Enlaces

  • La presentación de Leon Brocard, Paul Fenwick y Audrey Tang en formato PDF.
  • El ejemplar de primavera 2007 (Volumen 3, Ejemplar 2) de la revista The Perl Review a la que estoy subscrito.
  • Documentación de features de la rama en desarrollo (por el momento) de Perl 5.94