2013-03-08 5 views
4
package Bar; 
use Foo; 

sub bar { fooit "hello from bar"; } 

package Foo; 

sub fooit { 
    # Somehow I want this function to know it was called 
    # from the "Bar" module (in this case). 
} 

Предпочтительно, это было бы сделано без явно переданного аргумента, содержащего имя вызывающего модуля.Может ли функция определить, из какого модуля она была вызвана?

+1

Вы, вероятно, следует объяснить, почему вы хотите знать, как это вряд ли что-то вы можете рассчитывать на во всех возможных ситуациях для большинства целей. – tchrist

+0

Это для целей ведения журнала, поэтому я могу сказать: «fooit был вызван из Bar в 00:00:00». Не могли бы вы рассказать о подводных камнях здесь? – gcbenison

+1

Я часто пишу свои собственные функции 'debug', которые работают так, поэтому я знаю, откуда вы. Обычно люди не хотят знать, в какой пакет был скомпилирован вызывающий фрейм, а скорее его имя файла и номер строки, так как 'warn' и' die' не дают терминатора новой строки. «Ловушка», если таковая имеется, заключается в том, что любой может всегда писать '{package Other; some :: function()} ', и это не так, как если бы они находились в файле' Other.pm' или что-то в этом роде. На самом деле, они могут также вырезать файл и строку, но я думаю, если вы не находитесь в какой-то враждебной среде, это не имеет большого значения. – tchrist

ответ

6

Встроенная функция caller может использоваться для получения информации о текущем стеке вызовов.

sub fooit { 
    my ($pkg, $file, $line) = caller; 
    print STDERR "fooit was called from the $pkg package, $file:$line\n"; 
} 
+0

В свободное время создайте привязанную переменную '$ CALLER', которая всегда содержит эту информацию. :) – tchrist

2

caller без аргументов в скалярном контексте будет возвращать пространство имен вызывающего абонента.

my $caller = caller(); 

или

print caller()."\n";  # '.' forces scalar context 

или

print "".caller(), "\n"; # '.' forces scalar context 

Очень редко бывает, что вам нужно, если вы не пытаетесь воспроизвести поведение одного из подлодки Carp «s.

+0

И даже если вы, всегда есть «Carp: longmess». – tchrist

1

Использование встроенного caller должно быть самым простым и простым способом сделать это, но Devel::Backtrace также стоит увидеть модуль CPAN, который может предоставить более подробную информацию с помощью элегантного интерфейса.

package Foo; 
use Devel::Backtrace; 

sub fooit { 
    my $backtrace = Devel::Backtrace->new; 

    print $backtrace->point(1)->package, "\n\n"; 
    print $backtrace; 
} 

package Bar; 

sub bar { 
    Foo::fooit('hello from bar'); 
} 

package main; 

Bar::bar(); 

Выход:

Bar 

Devel::Backtrace::new called from Foo (test.pl:5) 
Foo::fooit called from Bar (test.pl:14) 
Bar::bar called from main (test.pl:19) 
Смежные вопросы