什么时候应该使用包变量和词法变量(有什么区别)?

时间:2009-06-19 19:17:29

标签: perl variables scope package lexical

我在Perl Monks上查看一些较旧的Perl代码,以找出使用Win32 :: OLE和MS Word进行编程的代码。在整个代码中分散的是名称为 $ MS :: Word 等的变量,其声明中没有包含“ my ”。在Google上阅读了一下之后,我了解这些被称为“包变量”与使用 my 声明的“词汇变量”。

我的第一个问题是'什么是包变量?'。我(想)我理解词汇变量是什么,但是我不明白包变量的用途或者它们的用法与词法有何不同,所以我的第二个问题是,'词法和包变量有什么区别吗

3 个答案:

答案 0 :(得分:8)

您应该阅读MJD的Coping with Scoping

perldoc perlmod也很有用。

代码离这个世界很难看。它仅仅因为作者似乎认为$ author :: email很酷而践踏各种名称空间而没有引起任何关注。

更好的方法是使用哈希:

my %author = (
   email => 'author@example.com',
   ...
);

无需遍历符号表。

我确实有一些Win32::OLE例子:http://www.unur.com/comp/这些都不是艺术品,但我相信这种风格有所改进。另请参阅Why are the number of pages in a Word document different in Perl and Word VBA?

我要咆哮一下

@pgm::runtime_args = @ARGV ;

因此,我们放弃了标准@ARGV数组来践踏pgm命名空间。不仅如此,每个Perl程序员都知道@ARGV是什么。在任何情况下,脚本中都不再使用@pgm::runtime_args

$pgm::maxargs = $#pgm::runtime_args + 1 ;

当然,标量上下文中的@pgm::runtime_args将为我们提供该数组中元素的数量。我不知道为什么可能需要$pgm::maxargs,但如果是,那么这一行应该是:

$pgm::maxargs = @pgm::runtime_args;

我不会引用更多这些东西。我想这就是当Cobol程序员试图编写Perl时会发生的事情。

$program::copyright = "Copyright (c) 02002 - Kenneth Tomiak : All rights reserved.";

我很高兴他今年分配了五位数。雅永远不知道!

PS:我相信我的摘录是合理使用的。

答案 1 :(得分:7)

包变量存在于符号表中,因此,只要给出其名称,就可以从任何其他包或范围中读取或修改它。词汇变量的范围由程序文本确定。 perlsub联机帮助页中的"Private Variables via my()"部分提供了有关定义词汇的更多详细信息。

说我们有以下MyModule.pm

package MyModule;

# these are package variables
our $Name;
$MyModule::calls = "I do not think it means what you think it means.";

# this is a lexical variable
my $calls = 0;

sub say_hello {
  ++$calls;

  print "Hello, $Name!\n";
}

sub num_greetings {
  $calls;
}

1;

请注意,它包含一个包$calls和一个词法$calls。任何人都可以找到前者,但模块控制对后者的访问:

#! /usr/bin/perl

use warnings;
use strict;

use MyModule;

foreach my $name (qw/ Larry Curly Moe Shemp /) {
  $MyModule::Name = $name;
  MyModule::say_hello;
}

print MyModule::num_greetings, "\n";

print "calls = $MyModule::calls\n";

程序的输出是

Hello, Larry!
Hello, Curly!
Hello, Moe!
Hello, Shemp!
4
calls = I do not think it means what you think it means.

正如您所看到的,包变量是全局变量,因此所有常见的问题和建议都不适用。除非明确提供访问权限,否则MyModule包之外的代码不可能访问其词法$calls

经验法则是你几乎总是想要使用词汇。 Damian Conway的Perl Best Practices是直接的:“永远不要让变量成为模块界面的一部分”(强调原文)。

答案 2 :(得分:4)

包变量是全局变量;它们在整个程序中随处可见(甚至其他模块)。当您需要或需要这种级别的可见性和/或外部影响时,它们非常有用。例如,Text :: Wrap模块使用它们来允许单个配置点作为包装文本的列数。此外,包变量允许您使用称为“动态范围”的东西 - 但这是一个稍微高级且略带深奥的概念。

关于第二个问题,请参阅What is the difference between my and our in Perl?

相关问题