3.6 foreach制御構文
配列を処理するには便利そうなforeach。
さすが文字列を処理するのが得意なPerlです。
実際に動くところを見たいので、
例題を書き写してみます。
#!/usr/bin/perl -w
use strict;my $rock;
foreach $rock (qw/ bedrock slate lava /) {
print "One rock is $rock.\n"; #3つの岩の名前を表示する。
}
とすれば、
One rock is bedrock.
One rock is slate.
One rock is lava.
と表示される。
ほうほう、なるほど。
配列の要素を全部処理し終えれば
ループを抜けるんですね。
配列の要素数を明示的に求めなくても
処理できるのは、便利ですね。
配列の勉強のために、
@hogeを使って同様の処理をする場合も
考えてみます。
#!/usr/bin/perl -w
use strict;my @rocks = qw/ bedrock slate lava /;
foreach my $rock (@rocks) {
print "One rock is $rock.\n"; #3つの岩の名前を表示する。
}
foreachの中でmyで宣言するのが
マナーとしてよいのかどうかわかりませんが、
ワーニングも出ずに動きます。
なるほどねぇ。
と思ったら、直後にほぼ同じ例題がありました。
use strictを使っていないので、
宣言してませんが。
ついでにこれもやってみよう。
#!/usr/bin/perl -w
use strict;my @rocks = qw/ bedrock slate lava /;
foreach my $rock (@rocks) {
$rock = "\t$rock";
$rock .= "\n";
}
print "The rocks are:\n", @rocks;
で、
The rocks are:
bedrock
slate
lave
となる。
制御変数をループ内で変更できるってことですね。
加えて、
- 制御変数はループが終了すると、ループが開始する前の値に戻る。
んだそうです。
ってことは、上記のプログラムの末尾に
print "One rock is:\n", $rock;
なんて書いても、宣言されたのが制御変数としてなので、
コンパイルエラーになっちゃうよ、ってことですね。
試したら、確かにそうなりました。:-)
3.5 配列を文字列の中に展開する
ここで覚えたことのメモ。
- ダブルクォート文字列の中にメールアドレスを入れると、配列として解釈されちゃうYO!!
そりゃそうですよね。
@があるもんね。
そういう時はシングルクォートでやる、と。
pop, push, shift, unshift
- popは配列の最後尾の要素を取り出して、返す。
- pushは配列の最後尾の要素に追加する。
- shiftは配列の先頭の要素を取り出して、返す。
- unshiftは配列の先頭の要素に追加する。
あぁ素敵。
配列処理としては便利な演算子たち。
これを回せば全ての要素を舐めることができるんですね。
Cだとインデクスをインクリメントして
舐めるところですが。
P55の脚注に、ジョークという言葉に紛らわせて
筆者の主張が力強く書かれています。
配列に対してインデクス(添え字付けする)を使うということは、Perlの良さを活用していないことになります。もし添え字付けの代わりにpop、push、および類似の演算子を使うと、あなたのコードは、たくさんの添え字付けをする場合に比べて、たいてい速くなります。さらに、「添え字が1つずれてしまった」という間違い---いわゆる「植え木算エラー(fencepost error)」---を避けることができます。しばしば、初心者のPerlプログラマが(Cに比べてPerlのスピードがどれくらいかを知ろうとして)、C言語向けに最適化されたソートアルゴリズム(添え字付けを大量に含むもの)を、Perl向けにそのまま(大量の添え字付けを含んだまま)書き換えて、「何でこんなに実行が遅いのでしょう?」と質問してくることがあります。それに対する答えは、「ストラディバリウスのバイオリンを使って、釘を打つのは良い工作法とは言えません」というものです。
後半の大袈裟な比喩にはニヤリとさせられますが、
それにしてもこれらの演算子の価値はあります。
ただし添え字付けを使わずにこれらの演算子だけで実行するには
不便も多いので、両方できるところに価値があるんでしょう。
3章 リストと配列
リストはデータであり、配列は変数である
なるほど。
ここで学んだことのメモ。
- インデクスは0オリジン。
- 最後の要素は$#hogeで指せる。
-負のインデクスは-1、-2、-3のみ。ただし実際に使うのは-1のみ。
- リストリテラルは(1, 2, 3)で表現。
- 範囲演算子..は、左右のスカラー値の間を1ずつ増加するリストを生成する。例えば(1..5)とすれば、(1, 2, 3, 4, 5)と書くのと一緒。
- qw(quoted words またはquoted by whitespace)を使うと、シングルクォートの代わりに使える。
- qwは、デリミタに任意の記号を使える。
範囲演算子っていいですね。
値が文字列だったらエラーが出るんでしょうか。
qwのデリミタが任意の記号というのは、
一瞬なんでろうな、と思ったけど、
この本にも書いてあるように
どんな記号の文字列も容易に扱えるように、
ってことなわけで、素晴しい仕様ですね。
それ以前の話ですが、スカラー変数と配列は、
全く同じ表記でOKなんですね。Perlでは。
数値と文字列が同じくらいビックリしました。
確かに何が代入されるか、とか、
使用される演算子が何か、で確定できますから、
これで何の問題もないんですよね。
なんて自由度が高いんだろう。Perlって。
と、読み進めたら、ちょっと違った。
- 配列全体を指す場合は@hogeと書く。
なるほど、$hogeはやっぱり配列全体を
指すわけじゃないってことですね。
脚注に書いてある
Larryは、それぞれ$calar(scalar)と@rray(array)だから、ドル記号とアットマークを選んだ
っての、いいですね。
わかりやすくて。
このエントリは長くなりすぎたので
一旦休憩。旦~
2.12 練習問題
5問。
サクっと終わる。
こんな簡単なのでも、
プログラムを書いてちゃんと動くと嬉しい。
解答を見ると、chompを使っている。
なるほど、すっかり忘れていた。
こういう時に使うのね。