如果不使用';我的';,在Perl中只指定变量的名称?

如果不使用';我的';,在Perl中只指定变量的名称?,perl,variables,Perl,Variables,我多次注意到,当我不使用my创建变量时,我的代码不会出现任何错误/问题 我将给出一个例子(这只是一个脚本的摘录) 当我执行该操作时,会出现如下错误: Global symbol "$filename" requires explicit package name at script.pl line 12. 当我将$filename=shift更改为我的$filename=shift时,该错误就会消失,然后我就可以运行代码并接收结果了 但是,在不编写my的情况下,当我删除use warnings

我多次注意到,当我不使用
my
创建变量时,我的代码不会出现任何错误/问题

我将给出一个例子(这只是一个脚本的摘录)

当我执行该操作时,会出现如下错误:

Global symbol "$filename" requires explicit package name at script.pl line 12.
当我将
$filename=shift
更改为
我的$filename=shift
时,该错误就会消失,然后我就可以运行代码并接收结果了

但是,在不编写
my
的情况下,当我删除
use warnings
use strict
时,代码也正常工作,我从脚本中得到的结果与使用
my
的脚本相同

我的问题:


如果跳过
my
是一个错误并导致错误,那么为什么代码可以正常工作?当未写入
my
时,正在发生什么以及实际会发生什么?在某些情况下,它会导致错误和奇怪的问题吗?

你是对的,如果没有
使用严格的
,你可以不使用
my
,程序就会完成它的工作。这在像这样的两行中是可以的:

$text_to_print = 'hello there';
print "$text_to_print\n";
但即使在本例中,一个小的打字错误也可能会给您带来意想不到的结果,在更复杂的程序中,您将无法找到它:

$text_to_print = 'hello there';
print "$text_t_print\n";
# will print an empty line only
如果添加
则使用strict
使用警告
plus
my
变量,您将收到有关输入错误的警告

use warnings;
use strict;

$text_to_print = 'hello there';
print "$text_t_print\n";
# will print to stderr: Global symbol "$text_t_print" requires explicit package name at untitled.pl line 5....

my
的作用是将变量词法化为当前范围。通常在perl中,变量是全局变量,在一个作用域中对它们的更改会影响所有其他作用域。对于my,对变量的所有更改都是局部的

词法变量或全局变量的使用有两个非常明显的区别:一个是递归函数,另一个是闭包

如果您想递归地计算某些东西(比如,计算阶乘),如果您想使用一个全局变量,那么对该函数的每个后续调用都会对前一个调用造成冲击,从而留下一个无用的函数

下面是一个实践中的例子:

sub Factorial {
  $arg = shift; #pull the argument off
  return 1 if $first == 0; #stopping condition
  return $arg * Factorial($arg-1); #recurse
} 
这将始终返回0,因为当函数进一步向0递归时,它们会不断敲击
$arg
变量,直到它最终返回1。但当它回到我们的价值链时,它会不断乘以
$arg
的全局值,即零

这可以通过添加
my
操作符立即解决,这将使
$arg
成为词法。这意味着对函数的每个调用都有自己的概念,即
$arg
是什么,从而允许递归调用成功

闭包是词汇变量的另一个有趣方面。通过使用不带名称的
sub
,可以在perl中创建匿名子例程(在python和其他语言中称为
lambda
s)。这些类型函数的一个很好的用途是保存当前状态的某些方面以供以后使用。(我在TeX有丰富的背景,在那里,闭包经常被使用,这是
\edef
原语)

闭包可以用于记忆,即将处理繁重函数的结果保存在内存中。创建一个用于记忆另一个函数的函数的示例如下:

sub Memoize {
  my $func = shift; #pull function name off the argument stack
  my %cache;        #prepare to memoize
  my $stub = sub {  # anonymous function
      my $key = shift; 
      $cache{$key} = $func->($key) unless exists $cache{$key};
      #this caches the result if it doesn't exist
      return $cache{$key};
    };
  return $stub;
};
此函数装饰了一个现有的单参数递归函数ref(给定为
\&Factorial
,具有记忆化功能(实际上,您可能希望使用记忆化模块实现此功能,但这只是为了展示闭包的概念)。如果没有不同的词法变量,这将非常糟糕。缓存将在所有修饰函数之间共享。这里的结尾是,我们调用返回函数的任何时候都可以使用缓存的值,即使在该函数之外,我们可以继续使用名为
%cache
的不同哈希

这两个例子基本上都是从《高级Perl》一书中摘取的,这本书非常优秀,它帮助您理解Perl是一种严肃的编程语言,而不仅仅是一种编写管理脚本的方式。 当然,另一个答案有实际的理由解释为什么要使用严格的
,但是关于什么是词汇,还有一个完全不同的世界


如果您想知道,使用
use strict
获取全局变量的方法是在它们前面加上
our
main::

是否回答了您的问题?这不是让程序运行,而是创建健壮、可维护的程序。顺便说一句,您应该使用
打开我的$To..,一个实用的用法:简单地总是有<代码>使用警告;和使用严格;并认为它们是内置的而不是可选的。因此警告和错误正是需要解决的。
sub Memoize {
  my $func = shift; #pull function name off the argument stack
  my %cache;        #prepare to memoize
  my $stub = sub {  # anonymous function
      my $key = shift; 
      $cache{$key} = $func->($key) unless exists $cache{$key};
      #this caches the result if it doesn't exist
      return $cache{$key};
    };
  return $stub;
};