Можно ли получить доступ к таблице символов без отключения строгого режима? - PullRequest
4 голосов
/ 06 ноября 2019

В Perl следующий код очень распространен. Вы даже можете увидеть это в таких вещах, как constant.pm.

my $symtab;
{
  no strict 'refs';                                                                                                                              
  $symtab = \%{$pkg . '::'};
}

Если я просто удаляю строгий, я получаю

Невозможно использовать строку (main::) в качестве ссылки HASH при использовании «строгих ссылок»

Возможно ли это сделать вообще, не отключая strict?

Ответы [ 3 ]

3 голосов
/ 06 ноября 2019

Строгий не запрещает доступ, если вам не нужно создавать имя тайника:

use strict;
use warnings;
$Foo::Bar::baz = 42;
my $symtab = \%Foo::Bar::;
print "${$symtab->{baz}}\n";

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

use strict;
use warnings;
$Foo::Bar::baz = 42;
my $main_stash = \%::;
my $Foo_stash = $main_stash->{'Foo::'};
my $FooBar_stash = $Foo_stash->{'Bar::'};
print "${$FooBar_stash->{baz}}\n";

Package :: Stash предоставляет программный способ доступа к тайникам.

use strict;
use warnings;
use Package::Stash;
$Foo::Bar::baz = 42;
my $package = 'Foo::Bar';
my $stash = Package::Stash->new($package);
print "${$stash->namespace->{baz}}\n"; # dereferencing the glob to access the scalar slot
print "${$stash->get_symbol('$baz')}\n"; # retrieving the scalar slot of the glob directly

Caveat emptor: только потому, что строгие переменные не мешают доступу к иерархии тайников, это делаетЭто не значит, что это не случайно (и устойчиво к оптимизации времени компиляции), и в большинстве случаев предпочтительнее просто отключить строгие 'refs' и создать имя символа.

2 голосов
/ 06 ноября 2019

Невозможно обойтись без выключения strict. Но есть способы скрыть эту сложность. Есть несколько модулей, которые позволяют вам сделать это, не выключая strict самостоятельно - Symbol (входит в стандартную поставку), Symbol :: Get и Tie:: Символ - три примера.

1 голос
/ 06 ноября 2019

Скрывать тот факт, что вы делаете что-то, что не является строго безопасным, если вы находите способ делать это со строгим включением, только обманывает себя и своих читателей. И это плохая идея.


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

И да, это можно сделать без отключения strict. Таблица символов доступна через %::, так что вы можете проанализировать пакет и таким образом перемещаться по таблице символов. Например, \%{'Foo::Bar::'} становится \%{ $::{"Foo::"}{"Bar::"} }, хотя это предполагает существование пакета. Вы также можете сгенерировать Perl-код и использовать eval.

НО, нет причин делать это. Нужно включить строгое, чтобы предотвратить случайное поступление. Замаскирование того факта, что вы делаете что-то, что не является строго безопасным, обманывает только вас и ваших читателей. И это плохая идея. Нужно стремиться написать самодокументированный код, и ничто не говорит «это сложный, опасный код», такой как no strict 'refs';.

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