Есть ли в Perl разница между прямым псевдонимом glob и псевдонимом через тайник?

Есть ли в Perl какая-либо разница между следующими двумя конструкциями:

*main::foo = *main::bar

и

$main::{foo} = $main::{bar}

Похоже, что у них одна и та же функция (создание всех слотов в *main::foo с теми, которые определены в *main::bar), но мне просто интересно, всегда ли сохраняется эта эквивалентность.


person Eric Strom    schedule 06.07.2011    source источник
comment
Мне любопытно, что привело к этому. :)   -  person brian d foy    schedule 07.07.2011
comment
Первое вызывает ошибку, когда включены строгие 'subs' или strict, второе разрешено.   -  person MkV    schedule 07.07.2011
comment
Я писал цикл для псевдонимов нескольких имен методов вместе и начал задаваться вопросом, почему я всегда пишу {no strict 'refs'; *{'some::pkg'.$new} = *{'some::pkg'.$old}, когда $some::pkg::{$new} = $some::pkg::{$old} будет работать так же хорошо. Интуитивно они кажутся одинаковыми, но такие вещи, как связи/перегрузки/другая магия, могли бы иметь интересные последствия, если бы они обрабатывали копию по-разному, будь то ошибка или предполагаемое поведение.   -  person Eric Strom    schedule 07.07.2011
comment
@MkV =› пример в моем вопросе отлично работает под strict. полностью квалифицированный идентификатор освобождается от ограничений. пример в моем комментарии выше требует отключения строгих ссылок из-за символического разыменования, но не имеет ничего общего с самим глобусом.   -  person Eric Strom    schedule 07.07.2011
comment
Ага, подумай. Я думал о разнице между *foo = *bar и $::{foo} = $::{bar}, когда текущий пакет является «основным».   -  person MkV    schedule 08.07.2011
comment
@MkV => Этот пример подходит и для strict, я не уверен, к чему вы клоните.   -  person Eric Strom    schedule 09.07.2011


Ответы (4)


Возможно, это не та разница, которую вы искали, но между *main::foo и $main::{foo} есть две большие разницы; первый ищет глобус в тайнике во время компиляции, создавая его при необходимости, а второй ищет глобус в тайнике во время выполнения и не создает его.

Это может иметь значение для чего-либо еще в тайнике, и это, безусловно, может повлиять на то, получите ли вы предупреждение used only once.

person ysth    schedule 07.07.2011
comment
Для таких людей, как я, которые не разбираются в эзотерике Perl: Stashes and Globs : Тайник — это хеш, который содержит все различные объекты, содержащиеся в пакете. Каждый ключ тайника представляет собой имя символа (общее для всех различных типов объектов с одинаковым именем), а каждое значение в хэш-таблице представляет собой GV (значение глобуса). Этот GV, в свою очередь, содержит ссылки на различные объекты с таким именем... поездка на Perl никогда не заканчивается! - person David Tonhofer; 04.01.2016
comment
@DavidTonhofer, тем более что это не совсем точно; в некоторых случаях в тайнике могут быть значения, не являющиеся GV. - person ysth; 05.01.2016

Следующий скрипт:

#!/usr/bin/env perl

#mytest.pl

no warnings;


$bar = "this";
@bar = qw/ 1 2 3 4 5 /;
%bar = qw/ key value /;

open bar, '<', 'mytest.pl' or die $!;

sub bar {
    return "Sub defined as 'bar()'";
}
$main::{foo} = $main::{bar};

print "The scalar \$foo holds $foo\n";
print "The array \@foo holds @foo\n";
print "The hash \%foo holds ", %foo, "\n";
my $line = <foo>;
print "The filehandle 'foo' is reads ", $line;
print 'The function foo() replies "', foo(), "\"\n";

Выходы:

The scalar $foo holds this
The array @foo holds 1 2 3 4 5
The hash %foo holds keyvalue
The filehandle 'foo' is reads #!/usr/bin/env perl
The function foo() replies "Sub defined as 'bar()'"

Поэтому, если *main::foo = *main::bar; не делает то же самое, что $main::{foo} = $main::{bar};, я не знаю, как обнаружить практическую разницу. ;) Однако с точки зрения синтаксиса могут быть ситуации, когда проще использовать один метод, а не другой. ...всегда применяются обычные предупреждения о манипуляциях с таблицей символов.

person DavidO    schedule 06.07.2011
comment
я предполагаю, что любая разница (если она есть) будет заключаться в какой-то эзотерической магии или чрезмерно усердном алгоритме кэширования. синтаксически определенно есть различия, код присваивания glob в сочетании с no strict 'refs' в подпрограмме import немного короче (и быстрее), чем ручное разделение вызывающей программы и обход таблицы символов уровень за уровнем, что заставляет меня предпочесть синтаксис glob , но при записи на полное имя, известное заранее (или уже обрабатывающее тайник по какой-то другой причине), синтаксическая разница немного более мутная, отсюда и вопрос :) - person Eric Strom; 07.07.2011
comment
Заглянуть под капот — веселое развлечение. Я думаю, что есть ситуации, когда старая добрая нотация glob является самой ясной, в то время как есть другие ситуации, когда нотация $namespace::{key} понятнее. Какой бы ни был более ясным для конкретной потребности, это способ сделать это. :) Конечно, если человек может найти альтернативу просмотру таблицы символов, есть много причин избегать любого подхода по замыслу. - person DavidO; 07.07.2011

Доступ к тайнику как $A::{foo} = $obj позволяет вам размещать что угодно в таблице символов, в то время как *A::foo = $obj помещает $obj в ожидаемый слот typeglob в соответствии с типом $obj.

Например:

  DB<1> $ST::{foo} = [1,2,3]

  DB<2> *ST::bar = [1,2,3]

  DB<3> x @ST::foo
Cannot convert a reference to ARRAY to typeglob at (eval 7)[/usr/local/perl/blead-debug/lib/5.15.0/perl5db.pl:646] line 2.
 at (eval 7)[/usr/local/perl/blead-debug/lib/5.15.0/perl5db.pl:646] line 2
    eval '($@, $!, $^E, $,, $/, $\\, $^W) = @saved;package main; $^D = $^D | $DB::db_stop;
  @ST::foo;

;' called at /usr/local/perl/blead-debug/lib/5.15.0/perl5db.pl line 646
    DB::eval called at /usr/local/perl/blead-debug/lib/5.15.0/perl5db.pl line 3442
    DB::DB called at -e line 1
  DB<4> x @ST::bar
0  1
1  2
2  3
  DB<5> x \%ST::
0  HASH(0x1d55810)
   'bar' => *ST::bar
   'foo' => ARRAY(0x1923e30)
      0  1
      1  2
      2  3
person salva    schedule 07.07.2011

См. также "Скаляры против глобусов (*{} не должен возвращать FAKE globs)"

https://github.com/perl/perl5/issues/10625

person druid62    schedule 22.12.2019
comment
Хотя эта ссылка может ответить на вопрос, лучше включить сюда основные части ответа и предоставить ссылку для справки. Ответы только по ссылкам могут стать недействительными, если связанная страница изменится. - person slfan; 22.12.2019