Estoy enviando una subrutina un hash, y traer con my($arg_ref) = @_;
Pero, ¿qué es %$arg_ref
? ¿Está %$
desreferenciando el hash?
Estoy enviando una subrutina un hash, y traer con my($arg_ref) = @_;
Pero, ¿qué es %$arg_ref
? ¿Está %$
desreferenciando el hash?
$arg_ref
es un escalar dado que usa el sigil $
. Presumiblemente, tiene una referencia hash. Así que sí, %$arg_ref
deferencias que referencia de hash. Otra forma de escribirlo es %{$arg_ref}
. Esto hace que la intención del código sea un poco más clara, aunque más detallada.
citar perldata(1)
:
Scalar values are always named with '$', even when referring
to a scalar that is part of an array or a hash. The '$'
symbol works semantically like the English word "the" in
that it indicates a single value is expected.
$days # the simple scalar value "days"
$days[28] # the 29th element of array @days
$days{'Feb'} # the 'Feb' value from hash %days
$#days # the last index of array @days
Así que su ejemplo podría ser:
%$arg_ref # hash dereferenced from the value "arg_ref"
my($arg_ref) = @_;
agarra el primer elemento de la pila y lo coloca en una variable local llamada $arg_ref
argumento de la función. La persona que llama es responsable de pasar una referencia hash. Una forma más canónica a escribir que es:
my $arg_ref = shift;
Para crear una referencia a un hash que podría comenzar con un hash:
some_sub(\%hash);
O puede crear con una referencia a un hash anónimo:
some_sub({pi => 3.14, C => 4}); # Pi is a gross approximation.
En lugar de desreferenciar todo el hash de esa manera, puede tomar elementos individuales con
$arg_ref->{key}
Una buena breve introducción a las referencias (crearlas y usarlas) en Perl es perldoc perfeftut
. También puede read it online (u obtenerlo como un pdf). (Habla más sobre referencias en estructuras de datos complejas que en términos de entrada y salida de subrutinas, pero la sintaxis es la misma.)
Dado que es algo claro, esta construcción se utiliza para proporcionar una referencia hash como una lista de argumentos con nombre a un sub sino que también debe tenerse en cuenta que este
sub foo {
my ($arg_ref) = @_;
# do something with $arg_ref->{keys}
}
puede ser excesiva en comparación con apenas el desembalaje @_
sub bar {
my ($a, $b, $c) = @_;
return $c/($a * $b);
}
Dependiendo de la complejidad de la lista de argumentos es.
my %hash = (fred => 'wilma',
barney => 'betty');
my $hashref = \%hash;
my $freds_wife = $hashref->{fred};
my %hash_copy = %$hash # or %{$hash} as noted above.
Soo, ¿cuál es el punto de la flexibilidad de la sintaxis?Vamos a probar esto:
my %flintstones = (fred => { wife => 'wilma',
kids => ['pebbles'],
pets => ['dino'],
}
barney => { # etc ... }
);
realidad para estructuras de datos profundos como éste es a menudo más conveniente comenzar con una ref:
my $flintstones = { fred => { wife => 'Wilma',
kids => ['Pebbles'],
pets => ['Dino'],
},
};
OK, así que Fred se deja una mascota nueva, 'Velociraptor'
push @{$flintstones->{fred}->{pets}}, 'Velociraptor';
¿Cuántas mascotas tiene Fred?
escalar @ {Picapiedra -> {Fred} -> {}} mascotas
Vamos a alimentar ...
for my $pet (@ {flintstones->{fred}->{pets} }) {
feed($pet)
}
y así sucesivamente. La sopa de corchetes puede parecer un poco abrumadora al principio, pero al final es bastante fácil lidiar con ellos, siempre y cuando seas consistente en la forma en que los enfrentas.
El prototipado se puede utilizar para eliminar la responsabilidad de paso de referencia de la persona que llama. – chaos
No creo que enseñar prototipos a los nuevos programadores de Perl sea una buena idea. Era una gran barrera viniendo de C y Pascal. Necesitaba aprender el verdadero valor de pasar listas antes de que los prototipos tuvieran sentido para mí. Sin embargo, podría ser útil aquí. –
El $ sigil no significa una variable escalar. Significa un valor escalar *, como en $ hash {key} y $ array [$ num]. En este caso, es una variable escalar porque es un valor escalar y no hay caracteres de indexación después. –