在Perl中,有没有一种方法可以绑定一个stash?

8

AUTOLOAD可以在需要时定义子程序的方式类似,我想知道是否有一种方法可以绑定包的存储区,以便我可以拦截访问该包中的变量。

我尝试了以下思路的各种排列组合,但都没有成功:

{package Tie::Stash;
    use Tie::Hash;
    BEGIN {our @ISA = 'Tie::StdHash'}
    sub FETCH {
        print "calling fetch\n";
    }
}

{package Target}

BEGIN {tie %Target::, 'Tie::Stash'}

say $Target::x;  

最后一行出现Bad symbol for scalar ...错误,程序无法打印"calling fetch"。如果删除say $Target::x;这一行,程序可以正常运行并退出。

我猜测这个失败可能与符号表类似但不同于哈希表有关,因此标准的tie机制无法正常工作(或者可能是符号表查找从未调用tie魔术)。

有人知道这是否可能吗?最好使用纯Perl,但XS解决方案也可以。


如果你将 tie ... 调用从 BEGIN 块中移除,它是否能正常工作? - mob
如果你稍后再做绑定,那么 Perl 已经查找并获取了保存 $Target::x 的全局变量,因此什么也不会发生。尝试运行 perl -M0 = Terse foo.pl 以查看原因。 - Alex
2个回答

4
你遇到了编译时的内部错误("Bad symbol for scalar"),这是因为Perl正在尝试计算 '$Target::x' 应该是什么,你可以通过运行调试版的Perl来验证:
perl -DT foo.pl
...
### 14:LEX_NORMAL/XOPERATOR ";\n"
### Pending identifier '$Target::x'
Bad symbol for scalar at foo.pl line 14.

当您使用tie()绑定'::Target'时,我认为它的GV被替换为其他内容,因此最终尝试访问其内部哈希表的任何内容都无法实现。鉴于tie()有点混乱,我怀疑您尝试的操作不会成功,这也可以从p5p上的这组(旧的)交流中得出。

https://groups.google.com/group/perl.perl5.porters/browse_thread/thread/f93da6bde02a91c0/ba43854e3c59a744?hl=en&ie=UTF-8&q=perl+tie+stash#ba43854e3c59a744


1
虽然使用tie来完成此操作是不可能的,但Variable::Magic允许您附加魔法到一个存储器中,从而实现类似的功能。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接