2010-08-01 8 views
7

Creo que el título se explica por sí mismo. Muchas veces tengo pequeños errores tipográficos y obtengo resultados inesperados al intentar acceder a claves hash no definidas. Sé que puedo añadir algo de defined comprobación antes de cada vez que acceda a un clave hash, pero me pregunto si hay alguna manera más clara para advertir contra tales casos ....hacer gritar Perl al intentar acceder a la clave hash no definida

mejor, de Dave

+1

No es necesario verificar si una clave está 'definida', sino si' existe'. No hay claves hash indefinidas * per se *. – pilcrow

+0

@pilcrow gracias por la corrección. –

Respuesta

14

Este es probablemente el mejor hecho con un hash atado. Las variables vinculadas le permiten definir la implementación de las operaciones de bajo nivel de la variable. En este caso, queremos ir a buscar un método especial que muere cuando se accede a claves inexistentes:

use warnings; 
use strict; 

{package Safe::Hash; 
     require Tie::Hash; 
     our @ISA = 'Tie::StdHash'; 
     use Carp; 

     sub FETCH { 
       exists $_[0]{$_[1]} or croak "no key $_[1]"; 
       $_[0]{$_[1]} 
     } 
} 

tie my %safe => 'Safe::Hash'; 

$safe{a} = 5; # ok 

print $safe{a}, "\n"; # ok 

$safe{b} = 10; # ok 

print $safe{bb}, "\n"; # dies 

en la implementación de Safe::Hash anterior, primera carga Tie::Hash que proporciona Tie::StdHash. La configuración @ISA a Tie::StdHash proporciona nuestro nuevo paquete con métodos de vinculación que se comportan de la misma manera que los hashes normales. Cada uno de los métodos de vinculación se describe en http://perldoc.perl.org/perltie.html

En este caso, el único método para anular es FETCH al que se le pasa una referencia al objeto vinculado oculto (un hashref en este caso) y la clave a usar. Comprueba si la ranura existe, y la devuelve o arroja un error

+0

muy bueno! ¿podría explicar la parte FETCH? ¿Es esta una palabra reservada? –

+0

Las variables vinculadas proporcionan un conjunto de métodos que puede anular y que le permiten especificar su comportamiento. Ver perltie para todos los detalles: http://perldoc.perl.org/perltie.html – friedo

7

Uso Hash :: util:

use Hash::Util "lock_keys"; 
my %hash = (foo => 42, bar => 23); 
lock_keys(%hash); 
print $hash{foo}; 
print $hash{baz}; 
print $hash{bar}; 

de salida:

42 
Attempt to access disallowed key 'baz' in a restricted hash at foo line 5. 

Hay otras funciones que permiten especificar qué teclas para permitir, no sólo por defecto a la AMS ya está allí.

+0

Gracias, esto es lindo, pero me pregunto si hay algo que se adapte mejor a mis necesidades. Me gustaría que se genere un error cada vez que intento acceder a una clave indefinida, a menos que el acceso sea una tarea. Mi hash es dinámico - Agrego claves y obtengo claves todo el tiempo - así que usar Hash :: Util me hará bloquear y desbloquear continuamente y también podría verificar si la clave está definida. –

+0

@David B: entonces probablemente quieras usar un hash vinculado, como sugiere Eric Strom. Aunque me pregunto qué estás haciendo exactamente con los valores que obtienes? Muchas operaciones ya deberían estar advirtiendo sobre valores indefinidos, suponiendo que tiene advertencias habilitadas. – ysth

4

Usted puede escribir una función simple para esto:

sub get { 
    my ($hash, $key) = @_; 
    die "No such key: $key" unless exists $hash->{$key}; 
    return $hash->{$key}; 
} 

my %hash = (...);  
my $val = get(\%hash, "mykey"); 
Cuestiones relacionadas