Внутренние переменные Perl.Следующие выражения такие же? - PullRequest
2 голосов
/ 22 мая 2019

У меня есть два выражения:

${ 'main::' }{ "_<$filename" }

и

${ "::_<$filename" }

эти два выражения одинаковы?

Ответы [ 2 ]

4 голосов
/ 23 мая 2019

Нет, но следующие значения эквивалентны:

${"_<$filename"}         # When this expression is found in package main
${"::_<$filename"}
${"main::_<$filename"}

${ $::{"_<$filename"} }
${ ${'::'}{"_<$filename"} }

${ $main::{"_<$filename"} }
${ ${'main::'}{"_<$filename"} }

Они относятся к переменной в корневом / главном пространстве имен, имя которой создается "_<$filename".


В качестве более ясного примера, все нижеприведенные значения эквивалентны (при условии, что код скомпилирован в пакет Foo::Bar для первых двух):

@moo                                  # Via hardcoded, unqualified name
@{'moo'}                              # Via symref using unqualified name

@Foo::Bar::moo                        # Via hardcoded, qualified name
@{'Foo::Bar::moo'}                    # Via symref using qualified name

@{ *Foo::Bar::moo }                   # Via hardcoded glob
@{ *{'Foo::Bar::moo'} }               # Via symref to glob

@{ $Foo::Bar::{moo} }                 # Via glob via hardcoded package
@{ ${'Foo::Bar::'}{moo} }             # Via glob via symref to package

@{ $Foo::{'Bar::'}{moo} }             # Via glob via hardcoded parent package
@{ ${'Foo'}::{'Bar::'}{moo} }         # Via glob via symref to parent package

@{ $::{'Foo::'}{'Bar::'}{moo} }       # Via glob via root package
@{ $main::{'Foo::'}{'Bar::'}{moo} }   # Same

Perl позволяет использовать имена символов в качестве ссылок.

$ perl -e'%h = ( a => 4, b => 5 ); my $ref = "h"; CORE::say $ref->{a};'
4

Они называются "символическими ссылками" (и они не разрешены при использовании use strict;). Следующее использует main:: как символическую ссылку:

${ 'main::' }{ "_<$filename" }

Однако делать это бессмысленно. Так как имя переменной в любом случае жестко закодировано, мы могли бы также использовать следующее:

$main::{ "_<$filename" }

Мало того, что это проще, это разрешено при использовании use strict;.


Но что такое %main::? Ну, это таблица символов для пакета main. Ключи %main:: - это имена символов (переменных), которые существуют в пакете main (без каких-либо символов).

Значения %main:: являются записями таблицы символов. Мы называем это "typeglobs", или "globs" для краткости. Разыменование глобуса, как если бы это была ссылка, обращается к переменной типа, соответствующего разыменованию. Например,

$main::{a}

возвращает

*main::a       # A glob

и

${ $main::{a} }

возвращает

$main::a

Это означает, что следующее возвращает глобус к переменной в пространстве имен main, имя которого создается "_<$filename"

$main::{ "_<$filename" }

Основным пространством имен является также корневое пространство имен. Это означает, что

$main::a

и

$::a

оба ссылаются на одну и ту же переменную. Это также означает, что

%main::

и

%::

оба ссылаются на одну и ту же переменную. Это также означает, что

$main::{ "_<$filename" }

и

$::{ "_<$filename" }

оба возвращают один и тот же глобус.


Мы установили, что следующее возвращает глобус для символа в корневом / главном пространстве имен, имя которого создается "_<$filename"

$::{ "_<$filename" }

Мы также установили, что следующие ссылки ссылаются на скаляр в корне / main, имя которого создается "_<$filename":

${ $::{ "_<$filename" } }

И, наконец, мы также установили, что следующее является символической ссылкой, которая ссылается на тот же скаляр:

${ "::_<$filename" }
4 голосов
/ 22 мая 2019

Почти

${ "::_<$filename" } - скалярная переменная в пространстве имен по умолчанию / main с именем, заданным "_<$filename"

%{"main::"} - это переменная stash для пространства имен по умолчанию / main, и ${"main::"}{"_<$filename"} - это типоглоб, который может быть с разыменованием с любым из операторов разыменования для извлечения значений в пространстве имен main с именем, заданным "_<$filename".

Итак, эти два выражения эквивалентны:

${"::_<$filename"}
${${"main::"}{"_<$filename"}}

Короткая демонстрация:

$ perl -de 1

Loading DB routines from perl5db.pl version 1.37
Editor support available.

Enter h or 'h h' for help, or 'man perldebug' for more help.

main::(-e:1):   1
  DB<1> $main::foo = 42                                                                                    

  DB<2> @main::foo = (1,2,3,"bacon")                                                                       

  DB<3> x ${"main::"}{"foo"}                                                                               
0  *main::foo
  DB<4> x ${${"main::"}{"foo"}}, @{${"main::"}{"foo"}}                                                     
0  42
1  1
2  2
3  3
4  'bacon' 
  DB<5> x @{"::foo"}, ${"::foo"}                                                                           
0  1
1  2
2  3
3  'bacon'
4  42
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...