Что означает __PACKAGE __-> {foo}? - PullRequest
19 голосов
/ 07 июля 2010

Я выполняю рефакторинг модуля perl в устаревшем коде, и это функция из модуля:

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

Этот модуль компилируется в use strict.И там не определены переменные пакета.Что означает __PACKAGE__->{user}?

Ответы [ 3 ]

14 голосов
/ 07 июля 2010

__PACKAGE__ - имя текущего пакета; Ваш код использует его как символьную ссылку на хеш. Поэтому, если ваш пакет foo, он устанавливает $foo::foo{'user'}. Это довольно странная вещь; Я подозреваю, что это может быть ошибка.

Поскольку это символическая ссылка, она не должна быть разрешена строгими правилами. Однако, похоже, что, по крайней мере, когда текущий пакет состоит из нескольких частей (например, Foo :: Bar, а не только Foo). Я бы не зависел от того, останется ли эта ошибка в силе.

7 голосов
/ 10 февраля 2013
use strict;
use warnings;
use 5.012;

{
    package X::Y;

    our $user = 10;
    say $user;

    say __PACKAGE__;

}


--output:--
10
X::Y

Имя пакета может быть 'X :: Y', но таблица символов для пакета называется 'X :: Y ::' (обратите внимание на конечные двоеточия).Таблица символов - это хэш perl, а ключи в% X :: Y :: hash - это глобальные имена, используемые в пакете X :: Y.Соответствующие значения - это typeglobs для каждого имени:

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

Но выражение в операторе:

__PACKAGE__->{user} 

эквивалентно:

'X::Y'->{user}

Я не могучтобы увидеть, как эта строка преуспеет в извлечении чего-либо из хэша с именем 'X :: Y ::' (оканчивается двумя двоеточиями).И на самом деле я получаю эту ошибку:

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.

Если код фактически создает где-то хеш с именем% X :: Y, то код будет работать без ошибок:

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

Как упоминалось в комментарии, хеш% X :: Y не имеет ничего общего с пакетом X :: Y.Фактически, строка:

%X::Y = ();

явно объявляет переменную с именем Y в пакете X.Пакет X и пакет X :: Y - это два разных пакета.

И переменные пакета не определены

Подменю является переменная пакета:

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

Тот факт, что typeglob для имени 'get_user' существует, означает, что в коде используется хотя бы одна глобальная переменная с именем 'get_user'.

0 голосов
/ 07 июля 2010

__PACKAGE__ - это хеш.Этот синтаксис обращается к ключевому значению.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...