有没有什么办法可以判断一个散列引用是否指向一个符号表?如何区分常规散列变量中的符号表?
也就是说,如何可以在功能
sub foo {
my ($hashref) = @_;
...
}
知道它是否已经被援引作为
foo(\%main::)
而不是
foo(\%main)
?
该应用程序是一个函数,有时tie
的哈希变量,但我想避免试图绑定符号表。
有没有什么办法可以判断一个散列引用是否指向一个符号表?如何区分常规散列变量中的符号表?
也就是说,如何可以在功能
sub foo {
my ($hashref) = @_;
...
}
知道它是否已经被援引作为
foo(\%main::)
而不是
foo(\%main)
?
该应用程序是一个函数,有时tie
的哈希变量,但我想避免试图绑定符号表。
看起来这可以通过C API使用HvNAME
来完成。以下是从perlapi:
HvNAME
如果藏匿不是藏匿返回藏匿, 或NULL的包名。见 SvSTASH,CvSTASH。
- 的char * HvNAME(HV *藏匿)
您可以查找以'::'结尾的键,这表示它有其他包,或者所有值都是符号引用。
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::');
}
的表现并不可怕。
这是一个很好的开始,并会得到我的方式出现95%,我想。这个测试对于空包('foo(\%empty :: package)'vs'foo({})')是不明确的,并且可能因为误报而被欺骗foo({'abc ::'=> * main :: abc ::})或者否定否定('$ emptypkg :: {“def”} =“xyz”; foo(\%emptypkg::)')。更安全吗? – mob 2011-03-01 22:29:00
我刚刚开始从运行'perl -MDevel :: Peek -e'Dump(\%a::),Dump(\%a)'''来推论。感谢您的链接,我可以做更少的货物查询。如果没有XS,你仍然可以做类似'$ is_a_symtable = do {$ sv = B :: svref_2object($ hashref); ref($ sv)eq'B :: HV'&& $ sv-> NAME};' – mob 2011-03-02 02:30:28