「<em>grep
次の要素を指定できますか?」という質問について、それを行う関数を作成してみましょう。
まず、最後のインデックスを除くすべてのインデックスをループします。インデックスの要素が条件を満たすと、次の要素が記憶されます。これは次のように書くことができます:
my @input = ...;
my @output = map { $input[$_ + 1] } # get the next element
grep { $input[$_] =~ /some condition/ } # grep all interesting indices
0 .. $#input - 1; # all indices but the last
または同等:
my @input = ...;
my @output;
for my $i (0 .. $#input - 1) {
push @output, $input[$i + 1] if $input[$i] =~ /some condition/;
}
これを関数に抽象化します。そのために、コールバック(または無名関数) を最初の引数として取ります。$_
次に、現在の要素に設定してこの関数を呼び出します。その関数の呼び出し元を汚染しないように、設定する前にその変数をローカライズする必要があります。
sub grepnext (&@) {
my $callback = shift;
# input is @_
my @out;
for my $i (0 .. $#_ - 1) {
# localize $_ and set it to the current element
local $_ = $_[$i];
push @out, $_[$i + 1] if $callback->();
}
return @out;
}
今できること:
my @after_red = grepnext { /red/ } qw(red cat blue dog);
grepnext
上記のように呼び出せるように宣言しました。これは(&@)
プロトタイプを使用します。プロトタイプは、特定の状況下で関数呼び出しの解析を変更できるようにする機能です。これらは非常に強力であり、通常は使用しないでください。名前付きパラメーターとは関係がなく、引数の検証には使用できません。また、サブルーチンは、それを呼び出す前に宣言する必要があります。
プロトタイプがなければ、次のフォームを使用する必要があります。
my @after_red = grepnext sub{ /red/ }, qw(red cat blue dog);
いずれにせよ、@after_red
には 1 つの要素が正しく含まれるようになりまし"cat"
た。