2010-10-01 16 views
6
$ cat test.pl 
use strict; 
use warnings; 

sub route { 
    print "hello, world!"; 
} 

my %h; 
$h{'a'} = 'route'; 

print "1\n"; 
$h{a}; 

print "2\n"; 
$h{a}(); 

print "3\n"; 
"$h{a}".(); 
$ perl test.pl 
Useless use of hash element in void context at test.pl line 12. 
Useless use of concatenation (.) or string in void context at test.pl line 18. 
1 
2 
Can't use string ("route") as a subroutine ref while "strict refs" in use at test.pl line 15. 
$ 

¿Cuál es la forma correcta de llamar al route()?¿Cómo puedo llamar a una subrutina cuyo nombre es un valor en un hash, en Perl?

+0

posible duplicado de [¿Cómo puedo llamar a un nombre de función que está almacenado en un hash en Perl?] (Http://stackoverflow.com/questions/1836178/how-do-i-call-a-function-name -that-is-stored-in-a-hash-in-perl) – Ether

Respuesta

13

Está intentando usar $ h {a} como referencia de símbolo. Y eso está explícitamente prohibido por "use strict". Si desactiva el modo estricto, a continuación, puede hacerlo de esta manera:

no strict; 
&{$h{a}}; 

Pero el mejor enfoque consiste en almacenar una referencia "real" a la subrutina en su hash.

#!/usr/bin/perl 

use strict; 
use warnings; 

sub route { 
    print "hello, world!"; 
} 

my %h; 
$h{a} = \&route; 

$h{a}->(); 
+3

Aunque estoy completamente de acuerdo con la sugerencia de davorg de usar referencias de código, también quiero señalar la función 'can' de perl. Dado el nombre del paquete en el que vive una función y el nombre de la función en sí, puede recuperar la referencia de código para esa función usando '$ package-> can ($ function)', sin tener que desactivar estrictos refs. – rafl

+2

'no hay estrictos 'refs'' es suficiente. – dolmen

3

Tiene que eliminar la referencia de la cadena que contiene el nombre de la rutina como un sub. Los paréntesis son opcionales.

my $name = 'route'; 
&{$name}; 

Como su nombre de rutina es un valor hash, debe extraerlo del hash. Además, como está utilizando strict (que es una buena práctica), tiene que deshabilitar localmente las comprobaciones.

{ 
    no strict 'refs'; 
    &{$h{a}}; 
} 

Sin embargo, como davorg sugirió en su respuesta, que sería mejor (en cuanto al rendimiento) para almacenar una referencia directa a la sub en su hachís, en lugar del nombre de la rutina.

Cuestiones relacionadas