无法调用方法状态 - 错误



我对 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(或ourlocal,但这些在这里不太可能)。

但是,当子例程退出时,子例程中的变量将消失,因此即使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 变量;它更适合可理解性。

相关内容

最新更新