有沒有什麼辦法可以判斷一個散列引用是否指向一個符號表?如何區分常規散列變量中的符號表?
也就是說,如何可以在功能
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