Подтвердить что ты не робот

Что означает __PACKAGE __-> {foo}?

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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:: - глобальные имена, используемые в пакете X:: Y. Соответствующие значения являются типами символов для каждого имени:

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

Но выражение в op:

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

Ответ 3

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