我试图了解use vars ($var);
的工作原理。我意识到如果我想全局声明一个变量,我可以使用use vars ($var);
或Perl 5.6以及更高版本我可以使用our $var;
然而,我仍然只是想了解它是如何工作的。查看the source,看起来您只是将变量声明为typeglob并将其设置为等于其自身的引用版本。什么?!
# My_Module.pm
use strict (vars, subs);
use CGI::Carp;
*My_Module::My_Global = \$My_Module::My_Global;
sub my_function {
$My_Global = 'Am I declared?';
}
现在这不起作用,我显然得到一个'未定义的符号'错误。那么use vars
如何做呢?
---------------- UPDATE ---------------
我确实完全复制了你的代码,用test use X;
而不是shell来运行它...
X.pm
use strict;
BEGIN { package X; no strict qw( refs ); *main::x = \${"main::x"}; }
print "Content-type: text/html\n\n"; # I added this line since not printing to shell
$x = 123; say $x;
1;
test.cgi
#!/usr/bin/perl
use strict;
use X;
...我之前遇到了相同的编译错误:
Global symbol "$x" requires explicit package name at X.pm line 4.
这只适用于shell而不是模块吗?
答案 0 :(得分:3)
分配对typeglob的引用是一种特殊的赋值;它仅使用引用替换引用类型的typeglob部分。此外,vars使用符号引用作为变量名称,而不是。 use vars
也在不同的包中执行,并且在编译时,而不是运行时。内联等价物将是:
BEGIN { package foo; *My_Module::My_Global = \${"My_Module::My_Global"} }
也就是说,使用全局变量通常是一个坏主意。使用不再支持的perl版本同样是个坏主意。
答案 1 :(得分:1)
只需使用变量就可以将其创建为(全局)包变量。
$ perl -wE'$x = 123; say $x;'
123
这非常危险,因此程序员通过使用use strict qw( vars );
告诉Perl禁止这样做。
$ perl -wE'use strict; $x = 123; say $x;'
Global symbol "$x" requires explicit package name at -e line 1.
Global symbol "$x" requires explicit package name at -e line 1.
Execution of -e aborted due to compilation errors.
但是,为了保持其有用性,严格的变量允许使用导入的变量而不会出错。
$ perl -wE'use strict; say $Config{version};'
Global symbol "%Config" requires explicit package name at -e line 1.
Execution of -e aborted due to compilation errors.
$ perl -wE'use strict; use Config qw( %Config ); say $Config{version};'
5.18.1
use vars
只是创建一个新变量并将其导出。
虽然你的代码接近这样做,但它有两个问题。
在代码中遇到对变量的任何引用之前,导入变量至关重要。需要进行两项更改才能在代码中修复此问题。
在评估赋值之前,必须编译赋值的操作数,因此在代码引用变量之前,您的赋值无法导入变量。
*Package::foo = $Package::foo; # XXX Compile-time lookup
*Package::foo = ${"Package::foo"}; # Runtime looup
*Package::foo = \( my $anon ); # Would work too.
在导入变量之前等待整个脚本编译,因此在严格已经禁止对变量的引用之后进行导入。您需要使用BEGIN { }
[1] 更快地执行导入。
对于要考虑导入的变量,执行导出的代码必须编译在与导出变量的包不同的包中。
如果我们应用这些修补程序,我们最终会得到以下结果:
$ perl -wE'
use strict;
BEGIN { package X; no strict qw( refs ); *main::x = \${"main::x"}; }
$x = 123; say $x;
'
123
注意:
请记住
use Module qw( ... );
与
基本相同BEGIN { require Module; Module->import(qw( ... )); }
换句话说,执行模块并在解析任何其他代码之前调用其import
方法。