5

名前付きの代わりに匿名のサブを使用したい理由は、Mason サブコンポーネント ( http://www.masonbook.com/book/chapter-2.mhtml#TOC-ANCHOR-7 )内でこれらのサブを定義したいからです。名前付きサブウーファーではうまく動作しません。

たとえば、そのようにコードを書く場合:

my ($first, $second);
$first = sub {
    my $val = shift;
    print "val: $val";
    $second->($val);
};
$second = sub {
    my $val = shift;
    if (0 < $val) {
        $val = $val - 1;
        $first->($val);
    }
};
$first->(10);

このアプローチには隠れた落とし穴 (メモリ リークなど) はありますか?

@Schwern で説明されているように、これらのサブルーチンのメモリは Perl によって解放されません。これは、それらの間に循環参照があるためです。

しかし、より具体的に言えば、メモリ割り当ては $val が増加するにつれて直線的に増加しますか、それとも呼び出しスタックの深さに依存しませんか? これらのサブルーチンを mason <%once> ブロックに配置できるため、その場合、これらのサブルーチンは一度だけ初期化されます。

4

2 に答える 2

2

以下は問題ありません。

sub first {
    my $val = shift;
    print "val: $val";
    second($val);
}

sub second {
    my $val = shift;
    if (0 < $val) {
        $val = $val - 1;
        first($val);
    }
}

first(10);

唯一の注意点は、サブルーチンにプロトタイプがある場合、または引数の括弧を省略したい場合は、サブルーチンを宣言する必要があるということです。

sub first($);
sub second($);

sub first($) {
    my $val = shift;
    print "val: $val";
    second $val;
}

sub second($) {
    my $val = shift;
    if (0 < $val) {
        $val = $val - 1;
        first $val;
    }
}

first 10;

一方、あなたのバージョンにはメモリリークがあります。最初のサブは、最初のサブへの参照をキャプチャする 2 番目のサブへの参照をキャプチャします。

$ perl -e'
   sub DESTROY { print "Destroyed\n" }

   {
      my ($first, $second);
      $first = sub { $second };
      $second = sub { $first };
      bless($first);
   }

   print("Subs should have been destroyed by now\n");
'
Subs should have been destroyed by now
Destroyed

解決策は、最初に anon subs を使用することにした理由によって異なります。

于 2015-09-29T18:49:02.477 に答える