subrutinas funciones perl hash subroutine

perl - funciones - ¿Cómo paso un hash a la subrutina?



funciones en perl (5)

Necesito ayuda para averiguar cómo hacer esto. Mi código:

my %hash; $hash{''1''}= {''Make'' => ''Toyota'',''Color'' => ''Red'',}; $hash{''2''}= {''Make'' => ''Ford'',''Color'' => ''Blue'',}; $hash{''3''}= {''Make'' => ''Honda'',''Color'' => ''Yellow'',}; &printInfo(%hash); sub printInfo{ my (%hash) = %_; foreach my $key (keys %_{ my $a = $_{$key}{''Make''}; my $b = $_{$key}{''Color''}; print "$a $b/n"; } }


Creo que quieres

my %hash; $hash{''1''}= {''Make'' => ''Toyota'',''Color'' => ''Red'',}; $hash{''2''}= {''Make'' => ''Ford'',''Color'' => ''Blue'',}; $hash{''3''}= {''Make'' => ''Honda'',''Color'' => ''Yellow'',}; printInfo(%hash); sub printInfo{ my %hash = @_; foreach my $key (keys %hash){ my $a = $hash{$key}{''Make''}; my $b = $hash{$key}{''Color''}; print "$a $b/n"; } }

En la línea printInfo(%hash) el %hash se expande a una lista con los pares clave-valor alternativos.

En printInfo , @_ es esta lista que, y asignada a %hash , crea nuevamente las claves con su valor correspondiente de los elementos alternos en la lista.


Eres muy, muy cerca. No hay %_ para pasar hashes, se debe pasar en @_ . Afortunadamente, los hashes se asignan utilizando un contexto de lista, por lo que

sub printInfo { my %hash = @_; ... }

lo hará funcionar!

Además, tenga en cuenta que el uso de & delante de la llamada de subrutina ha sido, en la mayoría de los casos, innecesario desde al menos Perl 5.000. Puede llamar a subrutinas de Perl como en otros idiomas en estos días, con solo el nombre y los argumentos. (Como @mob señala en los comentarios, hay algunos casos en que esto todavía es necesario; vea perlsub para entender esto más, si está interesado).


La manera fácil, que puede llevar a problemas cuando el código evoluciona, es simplemente asignando la matriz predeterminada @_ (que contiene todos los pares clave-valor como una lista par) al% hash que luego se reconstruye según corresponda. Entonces tu código se vería así:

sub printInfo { my %hash = @_; ... }

La mejor manera sería pasar el hash como referencia a la subrutina. De esta manera aún podría pasar más parámetros a su subrutina.

printInfo(/%hash); sub PrintInfo { my %hash = %{$_[0]}; ... }

Una introducción al uso de referencias en Perl se puede encontrar en perlreftut


La mejor manera de pasar hashes y matrices es por reference . Una referencia es simplemente una forma de hablar de una estructura de datos compleja como un único punto de datos, algo que se puede almacenar en una variable escalar (como $foo ).

Lea sobre las reference , de modo que entienda cómo crear una referencia y eliminar una referencia para recuperar sus datos originales.

Lo más básico: precede a su estructura de datos con una barra invertida para obtener la referencia a esa estructura.

my $hash_ref = /%hash; my $array_ref = /@array; my $scalar_ref = /$scalar; #Legal, but doesn''t do much for you...

Una referencia es una ubicación de memoria de la estructura original (más una pista sobre la estructura):

print "$hash_ref/n";

Imprimirá algo como:

HASH(0x7f9b0a843708)

Para volver a poner la referencia en un formato utilizable, simplemente coloque la referencia en el sigil correcto al frente:

my %new_hash = %{ $hash_ref };

Debería aprender sobre el uso de referencias, ya que esta es la forma en que puede crear estructuras de datos extremadamente complejas en Perl, y cómo funciona Perl orientado a objetos.

Digamos que quiere pasar tres hashes a su subrutina. Aquí están los tres hashes:

my %hash1 = ( this => 1, that => 2, the => 3, other => 4 ); my %hash2 = ( tom => 10, dick => 20, harry => 30 ); my %hash3 = ( no => 100, man => 200, is => 300, an => 400, island => 500 );

Voy a crear las referencias para ellos.

my $hash_ref1 = /%hash1; my $hash_ref2 = /%hash2; my $hash_ref3 = /%hash3;

Y ahora solo pasa las referencias:

mysub ( $hash_ref1, $hash_ref2, $hash_ref3 );

Las referencias son datos escalares , por lo que no hay problema en pasarlas a mi subrutina:

sub mysub { my $sub_hash_ref1 = shift; my $sub_hash_ref2 = shift; my $sub_hash_ref3 = shift;

Ahora, simplemente los desreferenciado, y mi subrutina puede usarlos.

my %sub_hash1 = %{ $sub_hash_ref1 }; my %sub_hash2 = %{ $sub_hash_ref2 }; my %sub_hash3 = %{ $sub_hash_ref3 };

Puede ver a qué se refiere una referencia usando el comando ref :

my $ref_type = ref $sub_hash_ref; # $ref_type is now equal to "HASH"

Esto es útil si quiere asegurarse de que se le está pasando el tipo correcto de estructura de datos.

sub mysub { my $hash_ref = shift; if ( ref $hash_ref ne "HASH" ) { croak qq(You need to pass in a hash reference); }

También tenga en cuenta que estas son referencias de memoria, por lo que la modificación de la referencia modificará el hash original:

my %hash = (this => 1, is => 2, a => 3 test => 4); print "$hash{test}/n"; # Printing "4" as expected sub mysub ( /%hash ); # Passing the reference print "$hash{test}/n"; # This is printing "foo". See subroutine: sub mysub { my $hash_ref = shift; $hash_ref->{test} = "foo"; This is modifying the original hash! }

Esto puede ser bueno: le permite modificar los datos pasados ​​a la subrutina, o mal, le permite modificar involuntariamente los datos pasados ​​a la subrutina original.


Puedes pasarlos como

  1. La lista de argumentos do_hash_thing( %hash )
  2. Una referencia al hash en la lista de argumentos `do_hash_thing (@args_before, /% hash, @args_after)
  3. Como referencia por prototipo , trabajando como keys y otros operadores de hash.

La lista funciona así:

sub do_hash_thing { my %hash = @_; ... } do_hash_thing( %hash );

Esto también te permite "transmitir" argumentos hash también:

do_hash_thing( %hash_1, %hash_2, parameter => ''green'', other => ''pair'' );

Por referencia funciona de esta manera:

sub do_hash_thing { my $hash_ref = shift; ... } do_hash_thing( /%hash, @other_args );

Aquí por prototipo (/%@) . El prototipo hace que Perl busque un hash en el primer argumento y lo pase por referencia.

sub do_hash_thing (/%@) { my $hash_ref = shift; ... } do_hash_thing( %hash => qw(other args) ); # OR do_hash_thing %hash => qw(other args);

Advertencia: los prototipos no funcionan con métodos.