无法调用方法状态 - 错误

时间:2012-05-30 01:07:56

标签: perl

我是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.  "

请帮助我了解这意味着什么以及为什么要来解决它...? 据我所知,“state”与其他语言(C / Java)中的“static”同义。我错了吗?

2 个答案:

答案 0 :(得分:9)

state是一个相当新的功能(自Perl 5.10起),默认情况下未启用。启用它:

use feature 'state';

使用state等同于在Java中使用静态变量。在没有状态的情况下执行此操作的另一种方法是使用$previous之外的简单my声明greetPerson,这意味着它在整个脚本范围内。

顺便说一句,你还应该在所有脚本中包含这些行,以便在赛道上节省很多麻烦:

use strict;
use warnings;

此外,在greetPerson中,您需要获取您的参数,您可以从@_获取参数。 E.g。

my ($name) = @_; # or
my $name = $_[0];

答案 1 :(得分:2)

是;你有错误的东西(但我也是如此)。 AFAIK,state在Perl中没有特定含义(但有人说这是一个必须启用的新功能)。


嗯... Perl 5.14.2有一个函数state。它是在5.10.0中引入的;我已经检查了我的机器上的5.10.0版本,它就在那里,即使我没有意识到它。 DavidO有助于确认state不属于5.8系列的Perl版本;该变化已在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(...)列表是至关重要的。他们提供列表上下文并使其工作。省略括号,事情就会出错。但是,列表上下文比我想在这里详细讨论的主题更大;请查看Llama书(或骆驼书,或在线)了解详情。

如果您要引用该参数一次,承诺不更改该值,则可以使用$_[0]表示法;如果您打算更频繁地使用它,请使用my变量。无论如何,最好使用my变量;它更易于理解。