pil*_*row 9 variables perl declaration
特定
# package main;
our $f;
sub f{}
sub g {}
1;
Run Code Online (Sandbox Code Playgroud)
我怎样才能确定$f,但是没有$g宣布?关闭袖口,我认为*{main::g}{SCALAR}可能是未定义的,但它是一个真正的 SCALAR参考.
背景:我想将一个变量导入main::,但是如果已经声明了该变量,则将carp或croak 导入.
编辑添加了一个f子程序来响应@ DVK的初始答案.
答案(2010-07-27)
这并不容易,但有可能.
一种eval技术是最便携的,工作在早于5.10的perls上.在最近的perls中,内省模块喜欢Devel::Peek和B可以区别对待.
我尽了最大努力,甚至试图询问eval STRING是否$main::f已通过our或声明my。(这需要复制、关闭,然后恢复STDERR以减少麻烦。)一旦更改了包,这些声明在临时之字形上就不再可见。
下面的技术将检测是否$f已通过声明
use vars qw/ $f /;
Run Code Online (Sandbox Code Playgroud)
代码如下:
package MyModule;
use warnings;
use strict;
# using $f will confuse the compiler, generating
# warnings of 'Variable "%f" is not available'
# although we're going for $main::f
my $__f = "from MyModule";
my %IMPORT_OK = (
'$f' => [f => \$__f],
);
sub import {
my($pkg,@imports) = @_;
my $callpkg = caller;
die "I don't speak your dirty Pig-Latin"
if $callpkg !~ /\A\w+(::\w+)*\z/ ||
grep !/\A[\$@%]\w+\z/, @imports;
foreach my $name (@imports) {
my($sym,$ref) = @{ $IMPORT_OK{$name} || [] };
die "unknown import: $name" unless $sym;
open my $saverr, ">&", \*STDERR or die "dup STDERR: $!";
close STDERR;
my $declared = eval qq{
package $callpkg;
my(undef)=$name;
1;
};
open STDERR, ">&", $saverr or print "restore STDERR: $!";
die "${callpkg}::$sym already exists" if $declared;
{
no strict 'refs';
*{$callpkg . "::" . $sym} = $ref;
}
}
}
1;
Run Code Online (Sandbox Code Playgroud)