[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