[Moscow.pm] функция не из нашего пакета
Vladimir V. Perepelitsa
inthrax на gmail.com
Пн Дек 29 03:18:02 PST 2008
Гм...
вообще-то да, референс функции имеет свое имя.
Есть Sub::Name, который позволяет это имя установить.
хотя это делается через XS.
use Devel::Peek;
Dump(\&foo);
SV = RV(0x81b32ac) at 0x815ba44
REFCNT = 1
FLAGS = (TEMP,ROK)
RV = 0x815b840
SV = PVCV(0x8172730) at 0x815b840
REFCNT = 4
FLAGS = ()
IV = 0
NV = 0
COMP_STASH = 0x815b7ec "Ap"
START = 0x817b0d0 ===> 2754
ROOT = 0x81b55d8
XSUB = 0x0
XSUBANY = 0
GVGV::GV = 0x8189f8c "Ap" :: "foo"
FILE = "xxx.pl"
DEPTH = 0
FLAGS = 0x0
OUTSIDE_SEQ = 262
PADLIST = 0x815b84c
PADNAME = 0x8189f5c(0x81b8a80) PAD = 0x8189f68(0x8171bd0)
OUTSIDE = 0x815ad6c (MAIN)
Вот там и указано GVGV::GV => Ap::foo
2008/12/29 Alexander Lourier <aml на rulezz.ru>:
> 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 mailing list
> moscow-pm на pm.org | http://moscow.pm.org
>
--
Best wishes,
Vladimir V. Perepelitsa aka Mons <inthrax на gmail.com>
Подробная информация о списке рассылки Moscow-pm