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
- La lista de argumentos
do_hash_thing( %hash )
- Una referencia al hash en la lista de argumentos `do_hash_thing (@args_before, /% hash, @args_after)
- 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.