[Moscow.pm] функция не из нашего пакета
Alexander Lourier
aml на rulezz.ru
Пн Дек 29 02:24:40 PST 2008
On Monday 29 December 2008 13:10:46 Vladimir V. Perepelitsa wrote:
> 2008/12/29 Alexander Lourier <aml на rulezz.ru>:
> > On Monday 29 December 2008 12:53:43 Dmitry E. Oboukhov wrote:
> >> >> &App::foo и &main::foo это ссылки на одну и ту-же функцию.
> >> >> так что выяснить что является настоящим именем, а что алиасом -
> >> >> неоднозначно. можно к примеру пройтись рекурсивно по всем неймспейсам
> >> >> и найти все имена по равенству ссылок.
> >>
> >> AL> Тоже хотел так ответить сначала. А потом подумал, что caller
> >> каким-то макаром AL> догадывается о настоящем имени.
> >>
> >> это caller вызваный ИЗНУТРИ функции.
> >> там можно и просто тупо __PACKAGE__ или даже __FILE__ юзать.
> >> а надо снаружи функции эту же задачу решить
> >
> > Чуть меняем пример:
> >
> > ==
> > package Ap;
> >
> > use base 'Exporter';
> > our @EXPORT=qw(foo);
> >
> > sub foo
> > {
> > $_[0]->();
> > }
> >
> > package main;
> >
> > Ap->import();
> >
> > sub foo1
> > {
> > my @caller = caller(1);
> >
> > use Data::Dumper;
> > print STDERR Dumper(\@caller);
> > }
> >
> > foo(\&foo1);
> > ==
> >
> > $VAR1 = [
> > 'main',
> > 'a.pl',
> > 23,
> > 'Ap::foo',
> > 1,
> > undef,
> > undef,
> > undef,
> > 256,
> > '',
> > undef
> > ];
> >
> >
> > На момент вызова caller __PACKAGE__ уже другой (main), но тем не менее,
> > функция идентифицирована как Ap::foo. Это значит лишь одно - что в где-то
> > глубоко в душе Perl помнит исходное имя каждой подпрограммы, даже
> > несмотря на то, что её экспортировали в другой неймспейс.
>
> Извините меня...
> а что еще может вернуть (caller 1)[3], если мы !внутри! сабы Ap::foo
> вызывает другую сабу и проверяем в ней caller(1)?
Вот о чём и говорю. Каким образом caller узнал, что мы внутри Ap::foo, а не
main::foo? Если бы Ap::foo и main::foo были совершенно симметричными
алиасами, то Perl не догадался бы, что это Ap::foo. Он бы подумал так - если
из пакета main вызывается foo(), значит это main::foo. А он так не думает. Он
лезет в табличку и вспоминает, что foo изначально все-таки объявлялось в Ap,
даже вспоминает, в каком файле это было и в какой строке. Поэтому,
практически уверен, что задачу можно решить без всякого рекурсивного обхода
пакетов, а просто добравшись до этой таблички.
Посмотрел исходники функции caller, ничего не понял в терминах (stash и иже с
ним) и закрыл. Может кто умеет всё это читать, разберётся.
Подробная информация о списке рассылки Moscow-pm