2010-07-07 19 views
19

Estoy refactorización un módulo de Perl en código heredado, y esto es una función del módulo:¿Qué significa __PACKAGE __-> {foo}?

sub get_user { 
    my $user = __PACKAGE__->{user}; 
    if (!defined $user) { 
     # more code 
     __PACKAGE__->{user} = $user; 
    } 
    return $user; 
} 

Este módulo se compila bajo use strict. Y no hay variables de paquete definidas. ¿Qué significa __PACKAGE__->{user}?

Respuesta

14

__PACKAGE__ es el nombre del paquete actual; su código lo está utilizando como una referencia de hash simbólica. Entonces, si su paquete es falso, está configurando $foo::foo{'user'}. Esto es algo extraño de hacer; Sospecho que puede ser un error.

Como es una referencia simbólica, no debe permitirse bajo estricto. Parece ser, sin embargo, al menos cuando el paquete actual tiene varias partes (por ejemplo, Foo :: Bar, no solo Foo). Sin embargo, no dependería de que este error siga vigente.

+1

Supongo que '__PACKAGE__' en el ejemplo de * eugene y * es' Compound :: Namespace :: Construction' en lugar de 'SimpleOne' (sin dos puntos), lo cual parece eludir la restricción para mí en 5.10. – pilcrow

+3

... por supuesto! Debido a que '__PACKAGE __-> {key}' en un espacio de nombre simple es, por ejemplo, 'main -> {key}' (error: 'Global symbol"% main "requiere nombre explícito del paquete'), pero en un espacio de nombre compuesto es, p., 'My :: Pkg -> {key}', que es una referencia totalmente calificada para el hash '% Pkg' en el paquete' My'. Esperaría un error "bareword", pero el procesamiento especial de '__PACKAGE__ debe eludir eso. – pilcrow

+2

ah. eso me parece un error. – ysth

-5

__PACKAGE__ es un hash. Esta sintaxis accede a un valor con clave.

7
use strict; 
use warnings; 
use 5.012; 

{ 
    package X::Y; 

    our $user = 10; 
    say $user; 

    say __PACKAGE__; 

} 


--output:-- 
10 
X::Y 

El nombre del paquete puede ser 'X :: Y', pero la tabla de símbolos para el paquete se llama 'X :: Y ::' (nota los dos puntos de fuga). Una tabla de símbolos es un hash perl, y las claves en% X :: Y :: hash son los nombres globales utilizados en el paquete X :: Y. Los valores correspondientes son los typeglobs para cada nombre:

use strict; 
use warnings; 
use 5.012; 

{ 
    package X::Y; 

    our $user = 10; 
    say $user; 

    say __PACKAGE__; 
    say $X::Y::{user}; #Hash name is %X::Y:: 


} 

--output:-- 
10 
X::Y 
*X::Y::user 

pero la expresión en el OP:

__PACKAGE__->{user} 

es equivalente a:

'X::Y'->{user} 

no veo cómo esa línea se tener éxito en recuperar cualquier cosa de un hash cuyo nombre es 'X :: Y ::' (termina en dos puntos). Y, de hecho, me sale este error:

use strict; 
use warnings; 
use 5.012; 

{ 
    package X::Y; 

    our $user = 10; 
    say $user; 

    say __PACKAGE__; 
    say $X::Y::{user}; 
    say __PACKAGE__->{user}; 
} 

--output:-- 
10 
X::Y 
*X::Y::user 
Use of uninitialized value in say at 2.pl line 13. 

Si el código en realidad crea un hash llamado% X :: Y en algún lugar, a continuación, el código se ejecutará sin errores:

use strict; 
use warnings; 
use 5.012; 


%X::Y =(); #This hash has nothing to do with the hash named 
      #%X::Y::, which is the symbol table for the 
      #X::Y package. 

$X::Y{user} = 'hello'; 


{ 
    package X::Y; 

    sub get_user { 
     say __PACKAGE__->{user}; 
    } 

    get_user; 
} 


--output:-- 
hello 

Como se ha mencionado en el comentar, el hash% X :: Y no tiene nada que ver con el paquete X :: Y. De hecho, la línea:

%X::Y =(); 

declara explícitamente una variable llamada Y en el paquete X. El paquete X y el paquete X :: Y son dos paquetes diferentes.

And there's no package variables defined

El sub nombre es una variable de paquete:

use strict; 
use warnings; 
use 5.012; 

{ 
    package X::Y; 

    sub get_user {say 'hello';} 

    say $X::Y::{get_user}; 

} 

--output:-- 
*X::Y::get_user 

El hecho de que un typeglob para el nombre 'get_user' existe, significa que el código utiliza al menos una variable global llamada 'get_user'.