如何区分符号表和常规哈希变量?

时间:2011-03-01 21:31:20

标签: perl glob

有没有办法判断哈希引用是否指的是符号表?

也就是说,功能怎么可能

sub foo {
    my ($hashref) = @_;
    ...
}

知道它是否被调用为

foo( \%main:: )

而不是

foo( \%main )

应用程序是一个有时tie个哈希变量的函数,但我想避免尝试绑定一个符号表。

2 个答案:

答案 0 :(得分:7)

看起来可以使用HvNAME从C API完成此操作。以下内容来自perlapi

  

HvNAME

     

返回藏匿包的名称,   如果存储不是存储,则为NULL。看到   SvSTASH,CvSTASH。

     
      
  1. char * HvNAME(HV * stash)
  2.   

答案 1 :(得分:3)

您可以查找以“::”结尾的键,这表示它有其他包,或者所有值都是符号引用。

  • 当然,即使在这里,也很难从存储符号的哈希(无论出于何种原因)告诉存储。我正在使用B::svref_2object,但即使存储在常规哈希中的存储中的符号也会返回$sym->can( 'STASH' )的内容。

我认为您可能会做的事情是通过符号表下降并查看存储是否指向完全相同的内存位置。

有点像这样:

use Scalar::Util qw<refaddr>;
my %seen;

sub _descend_symtable {
    $calls++;
    my ( $cand, $stash_name ) = @_;
    my $stash = do { no strict 'refs'; \%{ $stash_name }; };
    return if $seen{ refaddr( $stash ) }++;
    return $stash_name if $cand == $stash;

    my $result;
    foreach my $s ( grep { m/::$/ } keys %$stash ) {
        $result = _descend_symtable( $cand, "$stash_name$s" ) 
            and return $result;
    }
    return;
}

sub find_in_symtable { 
    my $needle = shift;
    %seen      = ();
    return _descend_symtable( $needle, 'main::' );
}

表现并非糟糕