1

私は次のコードを持っています:(この質問の目的のために非常に単純化されていますが、私が抱えている問題を完全に示しています)

#!/usr/bin/perl

use strict;
use warnings;

&outer;
my $connected_sub;

sub outer {
    print "HELLO\n";

    &$connected_sub;
    $connected_sub = sub {
        print "GOODBYE\n";
    }
}

プログラムを実行すると、次の出力とエラーが表示されます。

HELLO
Use of uninitialized value in subroutine entry at subTesting line 13.
Can't use string ("") as a subroutine ref while "strict refs" in use at subTesting.pl line 13.

私はここで何かを見落としていますか?私はこれの問題が何であるかを理解することも理解することもできません。

4

4 に答える 4

10

明確にするために:

サブルーチンの定義は、コンパイル段階で行われます。したがって、次のようなコードが機能します。

foo();

sub foo { print "No need to declare me before calling!"; }

しかし、そのコード行が呼び出されるまで、割り当ては実際には行われません。そのため、これは機能しません:

my $foo;

&$foo();

$foo = sub { print "Foo hasn't been set to me when you try to call me." }
于 2013-02-21T13:11:12.880 に答える
5

ここでやろうとしているのは、変数に匿名サブを割り当てることだと思います$connected_sub。これは良い方法ではありません。

あなたがやっていることは、空の変数を取り、それをコード参照として使用しようとし、コード参照をそれに割り当ててから、サブルーチンを終了してから変数宣言することですmy. 物事を行う最善の順序ではありません。

おそらくやりたいことは、次のように、変数に割り当てることができる値を返すことです。

my $connected = outer();
$connected->();

sub outer {
    print "HELLO\n";
    my $sub = sub { print "GOODBYE\n"; }
    return $sub;
}

サブルーチン内でレキシカル変数を使用するのはやや混乱すると思います。グローバル変数を使用する一般的な欠点に加えて、コードが実行されて変数が宣言される前に、サブルーチンもコンパイルされます。

また、サブルーチンを呼び出すときの標準的な方法は次のとおりです。

name(@args);

@args引数リストはどこにありますか。使用する&のは古いスタイルの perl であり、それを使用することには特別な意味があります (プロトタイプのオーバーライド)。変数で匿名サブを使用する場合は、->()表記法を使用します。

于 2013-02-21T13:13:01.853 に答える
4

$connected_sub は初期化されていません。匿名サブに割り当ててみてください:

my $connected_sub = sub {
   print "The code you need to run\n";
}

定義で、 &$connected_sub 呼び出しの後にコードをドロップします

これは変更された完全な例です:

#!/usr/bin/perl
use strict;
use warnings;


my $connected_sub = sub {
   print "GOODBYE\n";
};

&outer;

sub outer
{
        print "HELLO\n";
        &$connected_sub;
 } 
于 2013-02-21T13:05:04.900 に答える
2

$connected_stub初期化する前に使用しているようです。次のように、初期化を上に移動してみてください。

    $connected_sub = sub {
    print "GOODBYE\n";

    }
    &$connected_sub;
于 2013-02-21T13:08:12.297 に答える