我对 Perl 很陌生,正在尝试解决 Llama 书中的一些锻炼问题。问题是写一个子程序,如果一个人是第一个,就欢迎他,或者告诉他上一个在那里的人的名字。我的代码看起来像:
#! perl
# This is the greeter problem .
sub greetPerson{
state $previous = undef ;
if($previous eq undef){
print " Welcome ... u r the first n";
}
else{
print " Hi ... $previous was already here n";
}
$previous = $_;
return 0;
}
@code = ("ravi" , "teja" , "chandu");
greetPerson($code[0]);
greetPerson($code[1]);
greetPerson($code[2]);
我收到一条错误消息,说
"Can't call method state on undefined value in Line 6. "
请帮助我了解这意味着什么以及为什么它会到来以及如何解决它.. ?我知道"状态"在其他语言(C/Java)中是"静态"的同义词。我错了吗?
state
是一个相当新的功能(从Perl 5.10开始),默认情况下不启用。要启用它:
use feature 'state';
使用state
有点等同于在Java中拥有静态变量。另一种没有状态的方法是在 greetPerson
之外使用一个简单的my
声明$previous
,这意味着它的作用域在整个脚本中。
顺便说一句,您还应该在所有脚本中包含这些行,以节省很多麻烦:
use strict;
use warnings;
此外,在greetPerson
中,您需要获取您的论点,您可以从@_
获得
my ($name) = @_; # or
my $name = $_[0];
是的;你弄错了(但我也是)。 AFAIK,state
在Perl中没有特定的含义(但其他人说这是一个必须启用的新功能)。
嗯......Perl 5.14.2 有一个函数state
。 它是在 5.10.0 中引入的;我已经在我的机器上检查了一个 5.10.0 版本,它就在那里,即使我不知道它。 DavidO 帮助确认state
不在 Perl 版本的 5.8 系列中;此更改是在 5.10.0 中添加的。
所以,你需要一个足够现代的Perl版本,你需要用以下方法启用它:
use feature 'state';
如果未启用 state
功能,它看起来像一个方法调用,并且由于未定义该方法,因此您会收到看到的错误。 当然,即使启用它,它也是一个方法调用;或者,至少,它既被列为函数又被描述为函数,但它是具有特殊语义的内置函数。
以防万一你没有意识到,StackOverflow的一大优点是你通过回答问题来学习。
您可能正在寻找my
(或our
或local
,但这些在这里不太可能)。
但是,当子例程退出时,子例程中的变量将消失,因此即使my
也不是您所追求的。
在没有state
的情况下,你可能会使用一个全局变量(没有任何初始化,以便在第一次传递时它的值是undef
):
my $previous;
在函数外部,然后您只需在函数中引用它:
sub greetPerson{
if ($previous eq undef){
print " Welcome ... u r the first n";
}
else{
print " Hi ... $previous was already here n";
}
$previous = $_[0];
return;
}
这也修复了$_
与传递给函数的参数无关的问题。 你最好写:
sub greetPerson{
my($who) = @_;
if ($previous eq undef){
print " Welcome ... u r the first n";
}
else{
print " Hi ... $previous was already here n";
}
$previous = $who;
return;
}
您还应该使用一般的use warnings;
和use strict;
。 专家使用它们来确保他们没有犯愚蠢的错误。 新手也应该这样做。 这确实意味着您必须声明所有变量。
state
的一个好处是,它允许你隐藏一个变量,否则该变量必须是全局的(或者如果你正在使用模块,则隐藏在模块级别)在它真正所属的函数中。 因此,这是一个需要了解的有用功能。
从评论
我正在传递标量
(@code[0])
.那么,为什么我需要在那里使用@_[0]
?$_
不是那个吗?但不知何故,@_[0]
有效而不是$_
......你能解释一下吗?
完整的故事很复杂,但Perl将参数传递给函数的方式是作为一个数组。 在函数内部,参数在 @_
中可用。 变量 $_
与@_
无关(除了其名称的最后一个字符相同)。
注意:我已经修改了我的第一个示例以引用$_[0]
而不是@_[0]
。 这是访问@_
数组的第 0 个元素,仍然与$_
标量无关。 这是 Perl 确实引起混淆的一个领域。 (如果@_[0]
真的有效,那么要么我很幸运,要么 Perl 6 关于符号的一些想法正在渗透到 Perl 5.1x 中。
随着时间的流逝,您将习惯以下符号:
sub some_name_or_other
{
my($arg1, $name2, $obj3, $ref4, $hash5, @the_rest) = @_;
...
}
这会将前 5 个参数分配给标量变量,并将剩余的任何内容填充到局部数组@the_rest
中。 如果使用太少的参数调用它,则会得到undef
值。 my(...)
列表的括号至关重要。 它们提供列表上下文并使其正常工作。 省略括号,事情就会出错。 但是,列表上下文是一个比我想在这里详细讨论的更大的主题;详情请查看骆驼书(或骆驼书,或在线)。
如果你打算只引用参数一次,承诺不更改值,你可以使用$_[0]
表示法;如果你打算更频繁地使用它,请使用my
变量。 最好还是使用 my
变量;它更适合可理解性。