确定 Perl 代码引用的子例程名称

发布于 2024-12-05 00:07:14 字数 618 浏览 0 评论 0原文

如何确定 Perl 代码引用的子例程名称?我还想区分命名子例程和匿名子例程。

感谢 这个问题 我知道如何打印代码,但我仍然不知道如何获得这个名字。

例如,我想从以下内容获取“inigo_montoya”:

#!/usr/bin/env perl

use strict;
use warnings;

use Data::Dumper;
$Data::Dumper::Deparse = 1;

my $sub_ref = \&inigo_montoya;

print Dumper $sub_ref;



# === subroutines ===

sub inigo_montoya {
  print <<end_quote;
I will go up to the six-fingered man and say, "Hello. My name is Inigo
Montoya. You killed my father. Prepare to die."';
end_quote
}

How would one determine the subroutine name of a Perl code reference? I would also like to distinguish between named and anonymous subroutines.

Thanks to this question I know how to print out the code, but I still don't know how to get the name.

For example, I'd like to get 'inigo_montoya' from the following:

#!/usr/bin/env perl

use strict;
use warnings;

use Data::Dumper;
$Data::Dumper::Deparse = 1;

my $sub_ref = \&inigo_montoya;

print Dumper $sub_ref;



# === subroutines ===

sub inigo_montoya {
  print <<end_quote;
I will go up to the six-fingered man and say, "Hello. My name is Inigo
Montoya. You killed my father. Prepare to die."';
end_quote
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

夜光 2024-12-12 00:07:14

为什么不问,编译器看到了什么? (它会在匿名订阅者上返回__ANON__)。

#!/usr/bin/perl

use strict;
use warnings;

my $sub_ref = \&inigo_montoya;


use B qw(svref_2object);
my $cv = svref_2object ( $sub_ref );
my $gv = $cv->GV;
print "name: " . $gv->NAME . "\n";


sub inigo_montoya {
    print "...\n";
}

Why not ask, what the compiler sees? (It would return __ANON__ on anonymous subs).

#!/usr/bin/perl

use strict;
use warnings;

my $sub_ref = \&inigo_montoya;


use B qw(svref_2object);
my $cv = svref_2object ( $sub_ref );
my $gv = $cv->GV;
print "name: " . $gv->NAME . "\n";


sub inigo_montoya {
    print "...\n";
}
故事和酒 2024-12-12 00:07:14

Sub::Identify 正是这样做的,隐藏了所有令人讨厌的 B::svref_2object( ) 来自您的东西,这样您就不必考虑它。

#!/usr/bin/env perl

use strict;
use warnings;
use feature 'say';

use Sub::Identify ':all';

my $sub_ref = \&inigo_montoya;

say "Sub Name: ",   sub_name($sub_ref);
say "Stash Name: ", stash_name($sub_ref);
say "Full Name: ",  sub_fullname($sub_ref);

# === subroutines ===

sub inigo_montoya {
    print <<'    end_quote';
I will go up to the six-fingered man and say, "Hello. My name is Inigo
Montoya. You killed my father. Prepare to die."';
    end_quote
}

哪个输出:

$ ./sub_identify.pl 
Sub Name: inigo_montoya
Stash Name: main
Full Name: main::inigo_montoya

Sub::Identify does exactly this, hiding all that nasty B::svref_2object() stuff from you so you don't have to think about it.

#!/usr/bin/env perl

use strict;
use warnings;
use feature 'say';

use Sub::Identify ':all';

my $sub_ref = \&inigo_montoya;

say "Sub Name: ",   sub_name($sub_ref);
say "Stash Name: ", stash_name($sub_ref);
say "Full Name: ",  sub_fullname($sub_ref);

# === subroutines ===

sub inigo_montoya {
    print <<'    end_quote';
I will go up to the six-fingered man and say, "Hello. My name is Inigo
Montoya. You killed my father. Prepare to die."';
    end_quote
}

Which outputs:

$ ./sub_identify.pl 
Sub Name: inigo_montoya
Stash Name: main
Full Name: main::inigo_montoya
梦过后 2024-12-12 00:07:14

扩展 Jan Hartung 的想法(并废弃我自己的想法),您可以获得完全限定的名称和一些跟踪信息,无论它是什么或来自哪里:

use B qw(svref_2object);

sub sub_name {
    return unless ref( my $r = shift );
    return unless my $cv = svref_2object( $r );
    return unless $cv->isa( 'B::CV' )
              and my $gv = $cv->GV
              ;
    my $name = '';
    if ( my $st = $gv->STASH ) { 
        $name = $st->NAME . '::';
    }
    my $n = $gv->NAME;
    if ( $n ) { 
        $name .= $n;
        if ( $n eq '__ANON__' ) { 
            $name .= ' defined at ' . $gv->FILE . ':' . $gv->LINE;
        }
    }
    return $name;
}

Expanding on Jan Hartung's idea (and scrapping my own), you could get a fully qualified name and some trace information for no matter what it is or where it came from:

use B qw(svref_2object);

sub sub_name {
    return unless ref( my $r = shift );
    return unless my $cv = svref_2object( $r );
    return unless $cv->isa( 'B::CV' )
              and my $gv = $cv->GV
              ;
    my $name = '';
    if ( my $st = $gv->STASH ) { 
        $name = $st->NAME . '::';
    }
    my $n = $gv->NAME;
    if ( $n ) { 
        $name .= $n;
        if ( $n eq '__ANON__' ) { 
            $name .= ' defined at ' . $gv->FILE . ':' . $gv->LINE;
        }
    }
    return $name;
}
待"谢繁草 2024-12-12 00:07:14

我不确定从外部调用函数的名称,但您可以通过 caller 函数:

sub Foo {print "foo!\n";return (caller(0))[3];}
$function_name=Foo();
print "Called $function_name\n";

它具有以下输出:

foo!
Called main::Foo

当然,您可以将函数名称作为子例程返回的项目之一返回。这样,您可以捕获它并可以选择显示它(或在其他逻辑中使用它等)。

I'm not sure about calling the name of the function from the outside, but you can get it from within the subroutine via the caller function:

sub Foo {print "foo!\n";return (caller(0))[3];}
$function_name=Foo();
print "Called $function_name\n";

This has the following output:

foo!
Called main::Foo

Of course, you can return the function name as one of the items that the subroutine returns. That way, you can capture it and have the option of displaying it (or using it in other logic, etc).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文