Ответ 1
Похоже, что это можно сделать из C API с помощью HvNAME
. Ниже приведено perlapi:
HvNAME
Возвращает имя пакета, или NULL, если тайник не является тайником. Видеть SvSTASH, CvSTASH.
- char * HvNAME (HV * stash)
Можно ли указать, ссылается ли ссылка на хеш-ссылку на таблицу символов?
То есть, как могла функция
sub foo {
my ($hashref) = @_;
...
}
знать, был ли он вызван как
foo( \%main:: )
а не
foo( \%main )
?
Приложение - это функция, которая иногда tie
хэш-переменные, но я бы хотел избежать попытки привязать таблицу символов.
Похоже, что это можно сделать из C API с помощью HvNAME
. Ниже приведено perlapi:
HvNAME
Возвращает имя пакета, или NULL, если тайник не является тайником. Видеть SvSTASH, CvSTASH.
- char * HvNAME (HV * stash)
Вы можете искать ключи, заканчивающиеся на "::", что указывает на то, что у него есть другие пакеты, или все значения являются символами ref.
B::svref_2object
, но даже символы из тайника, хранящегося в регулярном хеше, вернут что-то для $sym->can( 'STASH' )
.Я думаю, что вещь, которую вы можете сделать, - это спуститься через таблицу символов и посмотреть, указывает ли 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::' );
}
Спектакль не был ужасным.