我可以在perl的子例程中声明全局变量吗?

问题描述 投票:1回答:2

我可以使用use strict在perl的子例程中声明全局变量吗?

请考虑以下代码:

#!/usr/bin/perl
# $Id: foo,v 1.5 2019/02/21 10:41:08 bennett Exp bennett $

use strict;
use warnings;

initialize();

print "$lorem\n";

exit 0;

sub initialize {
    # How would one delcare "$lorem" here such that it is available as
    # a global?

    $lorem = <<_EOM_
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
_EOM_
    ;
}

请注意,我不是问(ab)以这种方式使用全局变量是一个好主意;我确定不是。

我尝试了几种our$main::的组合,但它们都以你期望它们的方式失败。

在这一点上,我只是好奇。可以吗?我想知道是否某种带有BEGIN块的恶作剧会起作用。

以下内容可行,但正如@simbabque指出的那样,它很难看:

#!/usr/bin/perl
# $Id: foo,v 1.7 2019/02/21 19:48:26 bennett Exp bennett $

use strict;
use warnings;

initialize();

printf("$main::lorem\n");

exit 0;

sub initialize {
    # How would one delcare "$lorem" here such that is is available as
    # a global-ish?

    our $lorem = <<_EOM_
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
_EOM_
    ;
}
perl scope global-variables abuse
2个回答
5
投票

对于您的具体示例,您不需要全局变量。

Perl有包变量。这些是使用our创建的,也可以使用$namespace::访问(其中main是默认命名空间,$::也适用于此)。那些是全球性的,但我们很少称之为。

你需要记住,our是一个词法别名,所以如果你在sub中声明它,它将无法在外面使用,因为在更大的范围内没有词法别名。

use strict;

sub foo {
    our $bar = 123;
}

foo();
print $bar; # error

您需要在更大的范围内声明变量。

use strict;

our $bar;

sub foo {
    $bar = 123;
}

foo();
print $bar;

这将起作用,因为$bar现在可以在文件的范围内使用。

所有这些仅适用于启用use strict时。如果您没有声明变量,它将自动成为包变量。但是,如果启用strict,则必须声明所有变量。因此,您需要明确。

如果你在sub之外声明它,你也可以使用my

use strict;

my $bar;

sub foo {
    $bar = 123;
}

foo();
print $bar;

由于您在脚本中执行此操作并且没有明确的包声明,因此我认为可以安全地假设不涉及其他模块。在这种情况下,如果你使用myour并不重要。

如果您在包含不同文件的包中使用它,那将会产生影响。使用my在文件范围内声明的变量是私有的,因为无法直接从外部访问它们。

package Foo;
use strict;

my $bar = 123;

### other file
use Foo;

# no way to get $bar as there is no $Foo::bar

但是如果你使用our(或过时的use vars),它将成为一个包变量。

package Foo;
use strict;

our $bar = 123;

### other file

use Foo;
print $Foo::bar;

我可以在Perl的子程序中声明全局变量吗?

是的,您可以使用our在子例程中声明包变量。但是你不能在它们声明的范围之外作为词法变量访问它们,所以你需要使用它们的完全限定的包名来访问它们,这很难看。


0
投票

我相信答案是“不”。不是use strictuse strict的功能之一是检查你是否在声明之前使用变量。

如上所述,想要做到这一点的想法与use strict的编译时检查不一致。

感谢@simbabque帮助我更清楚地思考这个问题。

而不是删除use strict,我将把巨大的$lorem类型变量的丑陋(并且有很多它们)移动到一个单独的包中。

-E

© www.soinside.com 2019 - 2024. All rights reserved.