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

rom*_*das 5 variables perl scope package lexical

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

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

Sin*_*nür 9

您应该阅读MJD的应对范围.

perldoc perlmod也很有用.

代码离这个世界很难看.它仅仅因为作者似乎认为$ author :: email很酷而践踏各种命名空间而不用担心.

更好的方法是使用哈希:

my %author = (
   email => 'author@example.com',
   ...
);
Run Code Online (Sandbox Code Playgroud)

践踏符号表不是必需的.

我有几个Win32::OLE例子:http://www.unur.com/comp/这些都不是艺术品,但我相信这种风格有所改进.另请参阅为什么Word文档中的页数在Perl和Word VBA中有所不同?

我要咆哮一下:

@pgm::runtime_args = @ARGV ;
Run Code Online (Sandbox Code Playgroud)

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

$pgm::maxargs = $#pgm::runtime_args + 1 ;
Run Code Online (Sandbox Code Playgroud)

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

$pgm::maxargs = @pgm::runtime_args;
Run Code Online (Sandbox Code Playgroud)

我不会引用更多这些东西.我猜这是Cobol程序员尝试编写Perl时会发生的事情.

$program::copyright = "Copyright (c) 02002 - Kenneth Tomiak : All rights reserved.";
Run Code Online (Sandbox Code Playgroud)

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

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


Gre*_*con 8

包变量存在于符号表中,因此根据其名称,可以从任何其他包或范围中读取或修改它.词汇变量的范围由程序文本确定.perlsub联机帮助页中的"通过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;
Run Code Online (Sandbox Code Playgroud)

请注意,它包含一个包$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";
Run Code Online (Sandbox Code Playgroud)

该程序的输出是

Hello, Larry!
Hello, Curly!
Hello, Moe!
Hello, Shemp!
4
calls = I do not think it means what you think it means.
Run Code Online (Sandbox Code Playgroud)

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

经验法则是你几乎总是想要使用词法.Damian Conway的Perl最佳实践是直接的:" 永远不要让变量成为模块界面的一部分 "(强调原文).


Mic*_*man 5

包变量是全局变量;它们在整个程序(甚至其他模块)的任何地方都可见。当您想要或需要这种程度的可见性和/或外部影响时,它们很有用。例如,Text :: Wrap模块使用它们为包装文本的列数提供单个配置点。此外,程序包变量允许您使用一种称为“动态作用域”的方法-但这是一个有点高级且有点深奥的概念。

关于第二个问题,请参阅我和我们的Perl有什么区别?