2009-02-18 16 views
7

Estoy enviando una subrutina un hash, y traer con my($arg_ref) = @_;

Pero, ¿qué es %$arg_ref? ¿Está %$ desreferenciando el hash?

Respuesta

17

$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. 
+0

El prototipado se puede utilizar para eliminar la responsabilidad de paso de referencia de la persona que llama. – chaos

+0

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í. –

+1

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. –

7

En lugar de desreferenciar todo el hash de esa manera, puede tomar elementos individuales con

$arg_ref->{key} 
4

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.)

1

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.

2
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.

Cuestiones relacionadas