2009-07-31 19 views
5

que quiero hacer, en Perl, el equivalente del siguiente código Ruby:¿Cómo puedo crear un hash anidado como una constante en Perl?

class Foo 
    MY_CONST = { 
    'foo' => 'bar', 
    'baz' => { 
     'innerbar' => 'bleh' 
    }, 
    } 

    def some_method 
    a = MY_CONST[ 'foo' ] 
    end 

end 

# In some other file which uses Foo... 

b = Foo::MY_CONST[ 'baz' ][ 'innerbar' ] 

Es decir, sólo quiero declarar una estructura de hash constante, anidada para su uso tanto en la clase como fuera. ¿Cómo?

+0

ya he establecido mi clase Perl (con bendiga , etc.), así que no necesito que se me muestre cómo hacerlo. – Pistos

Respuesta

8

Puede usar el módulo Hash::Util para bloquear y desbloquear un hash (claves, valores o ambos).

package Foo; 
use Hash::Util; 

our %MY_CONST = (
    foo => 'bar', 
    baz => { 
     innerbar => 'bleh', 
    } 
); 

Hash::Util::lock_hash_recurse(%MY_CONST); 

Luego, en algún otro archivo:

use Foo; 
my $b = $Foo::MY_CONST{baz}{innerbar}; 
+0

Gracias, Michael, esto es exactamente lo que necesito. Traté de usar lock_hashref, pero no parece estar definido para mí, pero está bien, puedo arreglarme con lock_hash. – Pistos

+0

Noté que puedo lograr lo que necesito simplemente con "nuestro", no necesito Hash :: Util. No me preocupa que otras personas se ocupen del hash después del hecho, simplemente necesitaba saber cómo definir una constante accesible en Perl. Tu código de ejemplo me mostró. – Pistos

+2

¿Entonces realmente no necesitas una constante? Las cosas Hash :: Util es la magia que evita que las personas cambien el hash. –

1

Aquí es una guía para los hash en Perl. Hash of Hashes

+0

Gracias, aunque he construido hashes anidados en general en Perl. Mi necesidad específica tiene que ver con usarla dentro y fuera de un paquete/clase. – Pistos

4

Ver Readonly:

#!/usr/bin/perl 

package Foo; 

use strict; 
use warnings; 

use Readonly; 

Readonly::Hash our %h => (
    a => { b => 1 } 
); 

package main; 

use strict; 
use warnings; 

print $Foo::h{a}->{b}, "\n"; 

$h{a}->{b} = 2; 

Salida:

 
C:\Temp> t 
1 
Modification of a read-only value attempted at C:\Temp\t.pl line 21 
+0

Readonly no está instalado en el sistema que estoy usando, y no tengo la libertad de instalar libremente nuevos módulos. Pero gracias por tu sugerencia. Me encontré con eso cuando busqué en Google. – Pistos

+4

@Pistos http://perldoc.perl.org/perlfaq8.html#How-do-I-keep-my-own-module/library-directory%3F –

+0

@Sinan: Gracias, pero eso no ayuda en mi caso. Puede confundir mis circunstancias con las de un usuario en hosting compartido o algo así. Las barreras no son técnicas, son sociales/políticas/administrativas. :) – Pistos

11

Usted puede también hacer esto en su totalidad con las órdenes internas:

package Foo; 
use constant MY_CONST => 
{ 
    'foo' => 'bar', 
    'baz' => { 
     'innerbar' => 'bleh', 
    }, 
}; 

sub some_method 
{ 
    # presumably $a is defined somewhere else... 
    # or perhaps you mean to dereference a parameter passed in? 
    # in that case, use ${$_[0]} = MY_CONST->{foo} and call some_method(\$var); 
    $a = MY_CONST->{foo}; 
} 

package Main; # or any other namespace that isn't Foo... 
# ... 
my $b = Foo->MY_CONST->{baz}{innerbar}; 
+1

Gracias, Ether. Voy a seguir con esta sintaxis, ya que me permite usar referencias de manera consistente en todas partes. Yo marcaría el suyo como la respuesta aceptada, pero llegó un poco tarde. :) – Pistos

+0

Hash :: Util :: lock_hash_recurse es una buena solución, pero me gusta la solución integrada. –

Cuestiones relacionadas