6

これはPerlクックブックから直接持ち上げられたコードです:

@colors = qw(red blue green yellow orange purple violet);
for my $name (@colors) {
no strict 'refs';
*$name = sub { "<FONT COLOR='$name'>@_</FONT>" };
}

異なる色の名前で6つの異なるサブルーチンを形成することが目的です。説明の部分では、本は次のように書かれています。

これらの関数はすべて独立しているように見えますが、実際のコードは実際には1回しかコンパイルされていません。この手法により、コンパイル時間とメモリ使用量の両方を節約できます。適切なクロージャを作成するには、匿名サブルーチンの変数はすべて字句である必要があります。これが、my ontheloop反復変数の理由です。

適切な閉鎖とはどういう意味ですか、そしてそれmyが省略された場合はどうなりますか?さらに、typeglobは字句変数に対して定義できず、エラーをスローする必要があるにもかかわらず、typeglobが字句変数を処理するのはなぜですか?

4

3 に答える 3

7

他の人が言及しているように、クックブックは「適切な」という用語を使用して、より高い字句スコープからの変数を運ぶサブルーチンが作成され、この変数に他の手段で到達できなくなるという事実を指します。クロージャのこの部分を覚えておくために、過度に単純化されたニーモニック「$color変数へのアクセスは「クローズ」されています」を使用します。

「typeglobsは字句変数に対して定義できません」というステートメントは、typeglobsに関するいくつかの重要なポイントを誤解しています。「「my」を使用してタイプグロブを作成することはできません」と読んだのは、いくぶん真実です。次のことを考慮してください。

my *red = sub { 'this is red' };

これは、「my」キーワードを使用してtypeglobを定義しようとしているため、「my*red」付近の構文エラーで終了します。

ただし、例のコードはこれを実行しようとはしていません。オーバーライドされない限りグローバルであるtypeglobを定義しています。字句変数の値を使用して、typeglobの名前を定義しています。

ちなみに、typeglobは字句的にローカルにすることができます。次のことを考慮してください。

my $color = 'red';

# create sub with the name "main::$color". Specifically "main:red"
*$color = sub { $color };

# preserve the sub we just created by storing a hard reference to it.
my $global_sub = \&$color;

{
  # create a lexically local sub with the name "main::$color".
  # this overrides "main::red" until this block ends
  local *$color = sub { "local $color" };

  # use our local version via a symbolic reference.
  # perl uses the value of the variable to find a
  # subroutine by name ("red") and executes it
  print &$color(), "\n";

  # use the global version in this scope via hard reference.
  # perl executes the value of the variable which is a CODE
  # reference.
  print &$global_sub(), "\n";

  # at the end of this block "main::red" goes back to being what
  # it was before we overrode it.
}

# use the global version by symbolic reference
print &$color(), "\n";

これは合法であり、出力は次のようになります

local red
red
red

警告の下で、これは「サブルーチンmain::redredefined」と文句を言います。

于 2012-08-21T16:09:37.490 に答える
6

「適切な閉鎖」とは、実際には閉鎖を意味すると私は信じています。$ nameが字句でない場合、すべてのsubsは同じ変数を参照します(その値は、forループの前にあった値にリセットされます)。

*$name*sigilが行う面白い種類の間接参照の参照として$nameの値を使用しています。$ nameは文字列であるため、シンボリック参照です(したがって、厳密な'refs'はありません)。

于 2012-08-21T15:56:54.233 に答える
1

perlfaq7から:

クロージャとは何ですか?

閉鎖はperlrefに文書化されています。

クロージャは、正確であるが説明が難しい意味を持つコンピュータサイエンスの用語です。通常、クロージャは、独自のスコープ外の字句変数への永続的な参照を持つ匿名サブルーチンとしてPerlに実装されます。これらの語彙は、サブルーチンが定義されたときに存在していた変数を魔法のように参照します(ディープバインディング)。

クロージャは、Perlの場合と同様に、関数の戻り値自体を関数にすることができるプログラミング言語で最もよく使用されます。一部の言語は無名関数を提供しますが、適切なクロージャを提供できないことに注意してください。たとえば、Python言語です。クロージャの詳細については、関数型プログラミングに関する教科書をご覧ください。スキームは、クロージャをサポートするだけでなく、奨励する言語です。

答えは、かなり詳細に質問に答えるために続けられます。

PerlのFAQは素晴らしいリソースです。しかし、誰も読んでいない場合、それらを維持するのは少し労力の無駄です。

編集(投稿の後半の質問に適切に回答するため):

1 /適切な閉鎖とはどういう意味ですか?- 上記を参照

2 / myを省略した場合はどうなりますか?-動作しません。それを試して、何が起こるかを見てください。

3 /なぜtypeglobが字句変数を処理しているのですか?-変数$nameは、操作するtypeglobの名前を定義するためにのみ使用されています。実際にはタイプグロブとして使用されていません。

それはもっと役に立ちますか?

于 2012-08-21T15:28:31.657 に答える