配列(5) スライス

配列(2) 番号で要素を取得する で、配列変数の後ろに[N]をつけてN番の要素を取り出してみましたが、perlintro によると[N..M]でN番からM番の要素を一気に、[I,J]でI番とJ番の要素をそれぞれとりだせる(スライスできる)みたいです。
スライスすると、配列が返ってくるのでしょうか? 1つの要素を取り出す時は「$array[N]」のように頭に「$」を付けましたが、perlintro の例文ではスライスする時は頭に「@」をつけています。

# arrtest6.pl
my @arr = ("A", "B", "C", "D", "E");
print @arr[0..2], "\n";   # ABC
print @arr[2..4], "\n";   # CDE
print @arr[0,2,4], "\n";  # ACE?
print @arr[0,2..4], "\n"; # ACDE? 

多分できるんじゃないかという事で、,(カンマ)と..(ドット2つ)を組み合わせて複雑な範囲指定をしてみました。

D:\dev\perl>perl arrtest6.pl
ABC
CDE
ACE
ACDE

予想通りうまくいきました。これは便利ですね。
スライスすると、どうやら配列で戻ってくるようですね。では、スライスして出てきた配列をさらにスライスするとどうなるんでしょう……?

# arrtest7.pl
my @arr = ("A", "B", "C", "D", "E", "F", "G");
print @arr[3..6][0,2], "\n";

ABCDEFG → DEFG → DF という順番でスライスしてみました。うまくいけば「DF」と表示されるはずです。
いつもの通り、まず「-cw」で構文チェックして……と、syntax errorがでてしまいました。

D:\dev\perl>perl -cw arrtest7.pl
syntax error at arrtest7.pl line 3, near "]["
arrtest7.pl had compilation errors.

どうやら書き方がまずかったみたいです。直接スライスしようとしたらダメなんでしょうか。カッコをつけてみましょう。

# arrtest7.pl
my @arr = ("A", "B", "C", "D", "E", "F", "G");
print (@arr[3..6])[0,2], "\n";

もう一度構文チェック。また syntax error です。でも、さっきとは違う表示です。

D:\dev\perl>perl -cw arrtest7.pl
print (...) interpreted as function at arrtest7.pl line 3.
syntax error at arrtest7.pl line 3, near ")["
arrtest7.pl had compilation errors.

エラーメッセージによると……ああ、なるほど。「print (@arr[3..6])」の部分で、print関数を @arr[3..6] を引数にして呼び出した、と勘違いされてしまったようです。
では、さらにもう1つカッコで囲んでしまいます。後ろの「, "\n"」の部分もカッコの中に入れないとダメですね。これにより、print関数を (@arr[3..6])[0,2], "\n" という引数で呼び出した、と解釈してもらえるはずです。

# arrtest7.pl
my @arr = ("A", "B", "C", "D", "E", "F", "G");
print((@arr[3..6])[0,2], "\n");

三度目の正直。構文チェックしてみます。

D:\dev\perl>perl -cw arrtest7.pl
arrtest7.pl syntax OK

ついに「syntax OK」がもらえました! ほっとしますね。(^_^;

D:\dev\perl>perl arrtest7.pl
DF

狙い通り「DF」が出力されました。カッコの位置によって色々勘違いされてしまいましたね。関数を呼び出す時や返り値を利用する時は、カッコを付けた方がいいみたいです。