|
|
|||||||||||||||||||||||||
|
IntroducciónEs muy común que se subestime el poder que te da Perl, eso es simplemente porque no se comprende muy bien como es que funcionan ciertas funciones o simplemente porque se ignoran por completo. En este tutorial vamos a jugar un poco con la función tie de perl y las variables de tipo hash. Para esto vamos a crear un ejemplo básico en donde podremos cambiar un poco el funcionamiento básico de nuestros hashes. Antes de comenzar es recomendable que si no tienen mucho conocimiento de como funcionan los hases lean el siguiente tutorial: Un vistazo a tieUsando el famoso perldoc de Perl, podremos ver que la sintáxis básica de la función tie es: tie VARIABLE,CLASSNAME,LIST La función tie creará un objeto nuevo sobre la variable VARIABLE la cual cumplirá con los métodos establecidos en la implementación. CLASSNAME es el nombre de la clase que describe el comportamiento de nuestro objeto. También existe otro argumento, LIST. Aquí pondremos una lista de cualquier argumento opcional que pasaremos a la función new de nuestro método, esto puede ser TIESCALAR, TIEHANDLE, TIEARRAY, o TIEHASH, dependiendo de la variable. Muchos piensan que la función tie sirve solamente para amarrar un hash a un archivos DBM, cuando la realidad es otra. Por ejemplo, tie generalmente se utiliza para la construcción de objetos persistente, es decir, donde sus atributos son almacenados de manera pseudo-permanente. Otro caso es el uso de Tie::Array donde puedes amarrar un array a un archivo. Así que básicamente cualquier tipo de dato Perl puede ser amarrado a cualquier cosa. Solamente es caso de escribir un objeto que contenga ciertos métodos pre-definidos.
Usando objetos amarradosLa distribución básica de Perl viene acompañada de módulos que hacen mímica de sus datatypes básicos. Por ejemplo el módulo Tie::StdHash dentro de Tie::Hash, hace mímica de un hash verdadero. Entonces podríamos amarrar un hash a este módulo de la siguiente manera: use Tie::Hash; my %hash; tie %hash, 'Tie::StdHash'; Para este momento tendríamos nuestra variable %hash enlazada al módulo Tie::StdHash que tiene la implementación completa para esta variable, así que funciona con un verdadero hash. Pero lo divertido apenas comienza. Como funciona es que debido a que tenemos amarrado el módulo Tie::StdHash al momento que usemos nuestro hash amarrado Perl llamará la funciones necesarias dentro del módulo. Por ejemplo, cuando uno crea una nueva llave, Perl llamará la función STORE, la cual se encuentra dentro de la implementación. Para poder amarrar un objeto a un hash, necesitamos implementación a los siguientes métodos. Todos los métodos éstan en mayúsculas:
Todos los métodos que vayas a usar deben de ser implementados para poder amarrar un hash con un objeto. Pero más adelante vamos a ver como podemos evitar esto heredando de Tie::StdHash, usando un paradigma básico de programación OO.
Nuestro hash personalYa que aprendimos un poco de tie y cómo es que funciona y ya que tenemos conocimiento de todos los métodos que debemos de implementar para poder amarrar un hash, es hora de ponernos manos a la obra. Para este ejemplo, vamos a hacer un hash que siempre guarde los valores en puras minúsculas. Es un ejemplo básico pero nos podrá dar un vistazo al poder de tie. Para empezar vamos a hacer un nuevo módulo para el objeto. He decidido ponerle "MiHashPersonal": package MiHashPersonal; Como solamente quiero cambiar un poco el funcionamiento del método STORE, para poder modificar la manera en que se van a guardar los valores en las llaves, no tiene caso que escriba toda la implementación del hash, para esto vamos a usar el módulo Tie::StdHash como base: use strict; use base('Tie::StdHash'); En la última línea le decimos a nuestro módulo que herede el comportamiento de Tie::StdHash usando el pragma base de Perl. Ya hasta aquí podríamos amarrar nuestro módulo a un hash: use strict;
tie %hash, 'MiHashPersonal'; Como va a funcionar es que cuando Perl busque un método primero lo va a buscar en 'MiHashPersonal', en caso de que no lo encuentre debido a que heredamos en el módulo de Tie::StdHash entonces Perl buscará ahí el método. De esta manera podremos implementar aquellos métodos que realmente nos interesa modificar. Ya había dicho que queremos modificar el método STORE, para ello vamos a crear una nueva función STORE en nuestro módulo: sub STORE{ } Como habíamos visto el método STORE recibe como argumentos una referencia al objeto amarrado, el nombre de la llave y el valor que queremos crear. sub STORE{ my ($self, $key, $val) = @_; } Teniendo estos argumentos debemos de crear la nueva llave y el nuevo valor, pero antes de hacer eso vamos a convertir el valor a minúsculas usando la función lc(): sub STORE{ my ($self, $key, $val) = @_; $self->{$key} = lc($val); } Ya que guardamos nuestro módulo podremos hacer algo así: use strict; my %hash; tie %hash, 'MiHashPersonal'; $hash{'llave1'} = "VALOR1"; print $hash{'llave1'} . "\n"; Vemos como el valor de "llave1" es "valor1". Ya tenemos nuestro propio hash personalizado que guarda todos los valores en minúsculas.
Un poco más de diversiónVamos a jugar un poquito más con esto. Pues ahora vamos a hacer que nuestro hash aparte de que todos los valores los guarde en minúsculas, vamos a hacer que tenga llaves especiales que nunca podrán ser eliminadas. Como va a funcionar es que cualquier llave que inicie con "i-" (de importante, jeje) nunca podrá ser eliminada. Para ello debemos de implementar el método DELETE. Entonces creamos una función llamada DELETE en nuestro módulo "MiHashPersonal": sub DELETE{ } Como sabemos el método DELETE recibe una referencia al objeto amarrado y el nombre de la llave que el usuario quiere eliminar. sub DELETE{ my ($self, $key) = @_; } Lo primero que vamos a checar es si la llave inicia con "i-" usando una expresión. En caso de que así sea vamos a retornar inmediatamente. sub DELETE{ my ($self, $key) = @_; return if $key =~ /^i-/; } En caso de que la llave no inicie con "i-" entonces si vamos a eliminar la llave del hash.
sub DELETE{ my ($self, $key) = @_; return delete $self->{$key} if $key !~ /^i-/; } En la línea que acabamos de poner eliminamos la llave solamente en el caso de que el nombre de la llave no inicie con "i-". En caso de que no sea así, retornamos el regreso de la llamada a la función delete() que en este caso sería el valor de la llave que acaba de ser eliminada. Listo, guardamos nuestro módulo y tenemos nuestro hash con llaves importantes que no pueden ser eliminadas: use strict;
tie %hash, 'MiHashPersonal'; $hash{'i-clave'} = "mi clave importante"; delete $hash{'i-clave'}; #intentamos eliminar la llave print $hash{'i-clave'} . "\n"; Si ejecutas el código verás que la llave i-clave no fue eliminada. Código FinalMódulo MiHashPersonal package MiHashPersonal; use strict; use base('Tie::StdHash'); sub STORE{ my ($self, $key, $val) = @_; $self->{$key} = lc($val); }
my ($self, $key) = @_; return delete $self->{$key} if $key !~ /^i-/; }
#!/usr/bin/perl use warnings;
#creamos una nueva llave print $hash{'llave1'} . "\n"; #el valor en minúsculas
#intentamos eliminarla #No se pueden eliminar llaves especiales
AgradecimientosQuisiera agradecer a Marco A. Manzo por hacer una revisión del tutorial y haber dado recomendaciones en cambios en el código, haciendo del tutorial un tutorial mejor.
Bibliografíaperldoc tie Changing Hash Behaviour with tie Documentación Tie::Hash
|
||||||||||||||||||||||||
|
|||||||||||||||||||||||||