2

私は 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)の「静的」と同義であることを理解しています。私が間違っている?

4

2 に答える 2

9

stateデフォルトでは有効になっていないかなり最近の機能 (Perl 5.10 以降) です。有効にするには:

use feature 'state';

使用stateすることは、たとえばJavaで静的変数を持つことと同じです。$previous状態なしでそれを行う別の方法は、単純なmy外部で宣言greetPersonすることです。つまり、スクリプト全体にスコープが設定されます。

余談ですが、これらの行をすべてのスクリプトに含めて、後で多くの問題を回避する必要があります。

use strict;
use warnings;

また、greetPersonから取得できる引数を取得する必要があります@_。例えば

my ($name) = @_; # or
my $name = $_[0];
于 2012-05-30T01:15:12.440 に答える
2

はい; あなたは物事を間違えました(しかし私もそうです)。 AFAIKはstate、Perlでは特定の意味を持ちません(しかし、他の誰かが、それを有効にする必要がある新機能だと言っています)。


うーん...Perl5.14.2には機能がありますstate。5.10.0で導入されました。私は自分のマシンで5.10.0バージョンをチェックしましたが、気づいていなかったのですが、そこにありました。 DavidOstateは、それが5.8シリーズのPerlバージョンにはなかったことを有益に確認しています。変更は5.10.0で追加されました。

したがって、Perlの十分に新しいバージョンが必要であり、それを有効にする必要があります。

use feature 'state';

このstate機能が有効になっていない場合は、メソッド呼び出しのように見えます。メソッドが定義されていないため、表示されるエラーが発生します。もちろん、有効になっている場合でもメソッド呼び出しです。または、少なくとも、関数としてリストされ、関数として記述されていますが、特別なセマンティクスを備えた組み込み関数です。

気づかなかった場合に備えて、StackOverflowの優れた点の1つは、質問に答えることで学習できることです。

あなたが探しているかもしれません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;一般的に使用する必要があります。専門家はそれらを使用して、愚かな間違いを犯していないことを確認します。初心者も同じことをする必要があります。これは、すべての変数を宣言する必要があることを意味します。

優れた点の1つは、state実際に属する関数内で、グローバルである必要がある変数(または、モジュールを操作している場合はモジュールレベルで非表示にする)を非表示にできることです。したがって、知っておくと便利な機能です。


コメントから

スカラーを渡してい(@code[0])ます。では、なぜ@_[0]そこで使用する必要があるのでしょうか。そうじゃ$_ないの?しかし、どういうわけか、@_[0]うまくいくのではなく$_...説明してもらえますか?

全体像は複雑ですが、Perlが引数を関数に渡す方法は配列です。関数内では、引数はで使用できます@_。変数$_はとは無関係です@_(名前の最後の文字が同じであることを除いて)。

:最初の例を、$_[0]の代わりに参照するように変更しました@_[0]。これは配列の0番目の要素にアクセスすることであり、それでもスカラー@_とは何の関係もありません。$_これは、Perlが混乱を引き起こす領域の1つです。(@_[0]実際に機能した場合は、幸運に恵まれたか、シジルに関するPerl6のアイデアのいくつかがPerl5.1xに忍び寄っています。)

時間の経過とともに、表記法に慣れるでしょう。

sub some_name_or_other
{
    my($arg1, $name2, $obj3, $ref4, $hash5, @the_rest) = @_;
    ...
}

これにより、最初の5つの引数がスカラー変数に割り当てられ、ローカル配列に残っているものがすべて詰め込まれ@the_restます。引数が少なすぎると呼び出すと、undef値が取得されます。リストの括弧my(...)は非常に重要です。それらはリストコンテキストを提供し、それを機能させます。かっこを省略すると、問題が発生します。ただし、リストコンテキストは、ここで詳細に説明するよりも大きなテーマです。詳細については、ラマの本(またはキャメルの本、またはオンライン)をご覧ください。

値を変更しないことを約束して、引数を1回だけ参照する場合は、$_[0]表記を使用できます。より頻繁に使用する場合は、my変数を使用してください。myとにかく変数を使用することをお勧めします。わかりやすくするのに適しています。

于 2012-05-30T01:15:44.927 に答える