2010-02-12 11 views
7

Tengo una clase con un método que devuelve un hash. Por lo general, me gustaría tener el resultado de este modo:¿Cómo desreferenciamos un hash que ha sido devuelto por un método de una clase?

%resp = $myclass->sub($foo); 

Y luego los miembros de acceso del hash devuelto como esto:

$resp{key}{subkey}; 

en el caso de un hash 2d.

Calculo que debe haber una manera de combinar esto en una sola línea, elegante, algo como esto:

$myclass->sub($foo)->{key}{subkey} 

Esto, obviamente, no se dereferenced correctamente como Perl vuelve este al intentar ejecutar el código:

Can't use string ("1/8") as a HASH ref

al tratar secuencias de eliminación de referencias al azar, de mirar "References quick reference" on Perlmonks, me ocurrió lo siguiente, que Perl no se queja, sino que también no devuelve lo que estoy buscando:

$%{$myclass->sub($foo)}->{key}{subkey} 

¿Alguien puede decirme cuál es la secuencia de escape de desreferenciación mágica para hacer esto?

+1

Todo el mundo parece querer hacer allí vive más duro girando dos perfectamente buenas líneas en una sola línea en mal estado. Sin duda hay mejores cosas en que pensar. :) –

Respuesta

1

devuelven un hashref en lugar de un hash:

$myclass->sub($foo)->{key}->{subkey}

+0

Mismo resultado que con -> before {key}. Gracias. – sgsax

+0

Mismo resultado también si lo saco -> en conjunto. – sgsax

+0

Whazzup con -1? Segunda solución trabajada. – DVK

2

me gustaría volver una referencia a un hash de la sub lugar. De lo contrario (probablemente) el hash se convirtió en una LISTA luego en un hash de nuevo por ninguna razón:

sub mysub() { 
    ... 
    return \%myhash; 
} 

Hay menos copiado involucrados al devolver la referencia por lo tanto más eficiente.

+2

el hash se convierte en una lista, no en una matriz. la distinción es sutil pero importante. –

+0

Puedo hacer que funcione. ¿Puede explicar la ventaja de devolver un hashref en lugar de un hash? Puedo volver a trabajar los otros métodos en la clase con bastante facilidad. ¡Gracias! – sgsax

+0

Gracias Eric. Quería escribir LIST, pero ha pasado un tiempo. Mi Perl está bastante oxidado ahora. – ziya

6

Cambio de la sub para devolver una referencia a un hash funcionaría mejor, pero para obtener la funcionalidad que buscas:

{ $myclass->sub($foo) }->{key}{subkey} 

que creará una referencia a un hash de la lista devuelta por sub y, a continuación, inmediatamente desreferenciar es

Editar: La ventaja de devolver un hashref desde su sub en lugar de un hash (como una lista) es en gran parte de rendimiento. En el caso hashref, el hash se crea una vez y luego se accede a él. En el caso de la lista, se crea el hash, luego se convierte en una lista, luego se crea de nuevo y luego se desmarca. Para hash pequeños esto no tomará mucho tiempo, pero para los más grandes, es solo trabajo innecesario para el tiempo de ejecución. Básicamente, si planea usar los datos como una lista en algunos lugares, y como un hash en otros, devolver el hash como una lista está bien. Pero si siempre planeas utilizarlo como hash, devolver la referencia es más claro y rápido.

+0

. Eso me proporciona exactamente lo que buscaba mientras mantenía mi código de clase existente. ¡Gracias! – sgsax

9

Lo que estás tratando de hacer no es ni elegante ni aconsejable. De alguna manera ha logrado invocar la rutina en el contexto escalar (eso es lo que corresponde al "1/8").

Devuelve una referencia hash.

Ahora, echar un vistazo a:

#!/usr/bin/perl 

package My::Mine; 

use strict; use warnings; 

sub test { 
    my %h = (
     a => { z => 1}, 
     b => { y => 2}, 
    ); 
    return %h; 
} 

package main; 

use strict; use warnings; 

my $class = 'My::Mine'; 

print { $class->test }->{a}{z}, "\n"; 

Eso no va a funcionar. En su lugar, tendrá que hacer:

print +{ $class->test }->{a}{z}, "\n"; 

Ahora, eso es elegante Ver perldoc -f print (No !).

En resumen, devuelva una referencia al hash.

Tenga en cuenta que el nuevo hash anónimo que está construyendo no es gratuito. Tampoco es el costo de devolver un hash como una lista plana de una subrutina.

+0

No obtengo para qué se usa el + aquí. Aprecio la educación. Gracias. – sgsax

+3

+1 para explicar claramente 1/8. Además, una desventaja más de devolver un hash: te arrulla con una falsa sensación de seguridad si piensas que "esto es una copia, así que puedo modificarlo de forma segura"; sin embargo, las partes internas de la estructura de datos siguen siendo referencias que no son clonado profundo para que no pueda modificarlos con seguridad. – DVK

+2

+ es una sugerencia para el analizador sintáctico de que el {...} constructo que sigue a la impresión no es un objeto indirecto para el método de impresión. esto se usa en situaciones como 'print {sub_returns_a_file_handle()}" cosas para imprimir, tenga en cuenta que no hay una coma antes de la cita abierta ";' –

0

Si siempre desea obtener sólo una subclave, escribir un breve subrutina para hacer eso por ti y olvidarse de su línea de golf. Una de las ventajas es que se puede añadir fácilmente algunas comprobaciones cordura:

sub get_subkey { 
     my($class, $arg, $key, $subkey) = @_; 

     my $hashref = $class->method($arg); 
     return unless ref $hashref; 

     return $hashref->{$key}{$subkey}; 
     } 
Cuestiones relacionadas