我是Perl的新手,希望在理解子程序方面有所帮助。在子程序中,某些变量是否总是未定义?这是因为子程序中的变量是私有的吗?那么,如果我想要定义所述先前未定义的变量,我将如何去做呢?提前致谢。
答案 0 :(得分:4)
Perl中的变量不是私有的,但它们的范围有限。例如在子例程中用my
声明它们时。子例程的参数存储在变量@_
。
do_stuff($foo, $bar);
sub do_stuff {
my ($first, $second) = @_; # direct assignment
print "First: $first, Second: $second\n";
}
my
声明使变量在词法上限定为周围的块{ ... }
,这意味着它们受到保护,并且当执行离开块时它们超出范围。
也可以使用数组函数shift
和pop
访问子例程的参数,这在Perl代码中很常见:
sub do_stuff {
my $first = shift;
my $second) = shift;
除了它还从@_
数组中删除了元素外,它也做了同样的事情。
了解更多:
答案 1 :(得分:2)
在原始的,未减轻的Perl中,变量在范围内是 global 。也就是说,它们存在于您的程序中,从您定义它们到脚本的末尾。此外,在Perl中,当您使用未定义的值时,变量会存在。在字符串中,这被视为空字符串。在数字中,它被视为零。
因此,在子程序中,如果在主程序中定义了一个变量,它就在子程序中定义:
$foo = "Hello";
call_sub();
sub call_sub {
print "$foo\n";
}
那将打印“你好”。
但是,没有人应该在这种模式下使用Perl,因为它很容易出错:
$name = "Bob"
print "Hello $Name!\n";
糟糕!我在定义它时使用了$name
,在使用它时使用了$Name
。另外,您不需要这样的全局变量。否则,子例程可能会覆盖主程序变量。使编写大型复杂程序变得非常非常困难。
为了解决这个问题,我们强烈建议您将这两行放在代码中:
use strict;
use warnings;
use warnings;
会发出各种各样的警告,例如未初始化的变量被视为字符串和数字。
use strict;
会带来更大的变化。简单地说(并且不正确),use strict
会强制您声明您的变量,然后才能使用它们。
use warnings;
use strict;
my $name = "Bob"
print "Hello $Name\n";
此程序无效,因为$Name
从未声明(您使用my
关键字声明变量)。您可以看到这将如何防止错误。
但是,声明这些类型的变量称为词法范围变量。也就是说,它们可以进出存在。如果在块中定义了变量,则在块之外将不定义该变量。可以将块视为花括号:
子程序是一个块
sub foo { # Curly brace starts the block
...
} # Curly brace ends the block
这意味着如果你在子程序中定义一个变量,它只在那个子程序中。
此外,while
和for
循环是块:
for my $foo ( @foo_list ) { # The variable $foo is only defined in this loop
...
} # End of block and end of loop
while ( my $foo = <@foo_list> ) { # Again, $foo is only in this block
...
} # End of the block
if ( $foo == $bar ) { # Another block
my $foo = 1; # $foo is defined in the block
} # $foo is no longer defined
你甚至可以使用花括号:
my $foo = 1;
print "$foo\n" # Prints 1
{
my $foo = 2; # Redefines $foo it's a different $foo!
print "$foo\n" # Prints 2
} # End of block, $foo in block is now out of scope
print "$foo\n"; # Prints 1 because the original $foo is in scope.
让我们来看看:
my $foo = 2;
my $bar = 5;
print "$foo\n"; # Prints 2
call_sub(5); # Prints "Foo is 5!"
print $foo\n"; # Prints 2
sub call_sub {
my $foo = shift; # Different $foo from main program!
print "Foo is $foo!\n";
print "Bar is $bar\n"; # Will print "Bar is 5" because $bar is in scope
} # Subroutine's $foo falls out of scope
正如您所看到的,$bar
是在我调用子例程之前定义的,因此它在子例程中定义并且仍在范围内。但是,我的子例程中的$foo
被重新声明,并一直保留到子例程结束并超出范围。因此,我的子程序使用$foo
不会干扰我的主程序。
所以,回答你的问题:
use strict;
。这将迫使您在变量可以使用之前声明它们。my
声明变量之前,不会定义变量。my
在程序开头声明所有变量,就像在Pascal中一样。在使用它们的地方声明它们,并在它们不需要时让它们超出范围。my
声明所有子例程变量是安全的。use warnings;
发出警告。最后,我撒了谎,但这是有充分理由的。 Perl中的变量比我提出的要复杂得多(很多)。您有名称空间的概念,包变量以及本地化变量的方法甚至不是本地的。即使与Perl合作多年的人也很难理解其后果。
use strict;
并没有真正强迫你声明变量。它会强制您使用通过my
声明的词法范围变量,或使用包变量的完全限定变量名(或使用our
宣布那些)。
但是,最后,use strict;
在某种程度上会强制您声明变量,因为您将在Perl中使用的99%变量将使用my
声明。当您了解有关Perl的更多信息时,您可以了解更多关于其他1%的内容。
有关详细信息,请查看PerlSub关于使用my
获取私有变量的信息,并查看PerlMod以获取有关的完整讨论包变量,使用 local ,以及(我怎么能忘记!)新引入的 state 变量。
答案 2 :(得分:1)
一般情况下,变量是用my命令定义的(从技术上来说,还有一些其他的变量,比如我们和本地,但我从不使用它们。)
定义变量类型:
my $variable
如果你在子程序中这样做,它将生成你需要的变量。在代码中使用strict指令通常是个好主意:
use strict
当你忘记定义事情时,这会给你一些警告。