| Top Page | プログラミング | Perl 目次 | prev | next | 索引 |

15. もっと短くスマートに書ける : いわゆる syntactic sugar

プログラミング言語の文法は,人間がコンピュータにやらせたいこと (で,コンピュータができること)がひととおり表現できるように 設計されています.そのような,プログラマの意図の表現のために 最低限必要な文法に加えて,人間がもっと楽して書けるように追加される書法は, ときに syntactic sugar (構文糖)と呼ばれます.

Perl はかなり豊富に砂糖がかかった言語ですが, 最初は少なく覚えてたくさん使うのがよかろうと思い, ここまでの解説では砂糖はなるべく控え目にしてきました.

でも,禁欲的な書き方にいつまでもこだわる必要はありません. 書きやすくなったり読みやすくなったりする書法があるなら利用しましょう. そんな書法をいくつか紹介します.


足し算と代入を簡単に

下の3行は,いずれも現在の $x の値を 1 増やします.

 $x = $x + 1;   # $x に 1 を加えたものを $x に代入する.
 $x += 1;       # 同じこと.
 ++$x;          # 同じこと.

単に右辺を左辺に代入するという最初の行の記法さえあれば十分で,したのような 書き方ができなくても意図の表現に困るということはありません. でも,よりコンパクトに書くために,下の二行のような syntactic sugar が 用意されています.

+= という代入演算子は前にも出てきました. これを使った書き方だと変数名を書くのが1回短くて済むというメリットがあるだけでなく, この変数の値を変化させるという意図も読み取りやすくなります.

++ は,変化量が1の場合に限り使える syntactic sugar です. 1だけ減らす-- という演算子もあります.


条件判断用の文の syntactic sugar

まず,条件判断用の文の syntactic sugar です.

if ( !($x == 1) ) {         #  $x が 1 と(数値として)等しくなかったら…
    print "$x is not 1 \n";
}

if ($x != 1) {              #  上に同じ
    print "$x is not 1 \n";
}

unless ($x == 1) {          #  上に同じ
    print "$x is not 1 \n";
}

数値の比較演算子としての == はすでに出てきました. 真偽を反転させる ! も出ました.これを組み合わせたのが最初の if 文です. 数値の比較演算子には,左右が等しく_ない_と真になる != もあります. これを使ったのが2番めです. さらに,if 文と逆に,() 内の条件が偽のときに {} で囲んだブロックを実行する unless 文というものもあります.これを使ったのが3番めです.

if と == と ! さえあれば済むはずですが, != や unless も用意されています. これらを使ったほうが書きやすい,読みやすい場合にはどんどん使いましょう.

if (! ... ) のかわりに unless ( ... ) と書けるのと同様, while (! ... ) のかわりに until ( ... ) とも書けます.

while  ( !($x == 1) ) {    #  $x が 1 と(数値として)等しくないあいだは…
    print "$x is not 1 \n";
    # ....
}

untill ($x == 1) {         #  上に同じ
    print "$x is not 1 \n";
    # ....
}

もうひとつ,条件判断の文の書き方です.if や unless は文のうしろにくっつける ことができます.

if ($x == 1) {                    # 1と等しかったらメッセ−ジを表示.
    print "$x is 1 \n";
}
print "$x is 1 \n" if ($x == 1);  # 同じこと


unless ($x == 1) {                # 1と等しくなかったらメッセ−ジを表示.
    print "$x is not 1 \n";
}
print "$x is not 1 \n" unless ($x == 1);  # 同じこと

たとえばこんな感じで使うと,読みやすくなります.

while ($line = <>) {
    chomp $line;
    next if $line eq "";  #  空白行だったら処理を飛ばして次を読む.
    #  ...
    #  何らかの処理
    #  ...
}


特殊変数

Perl には特殊変数と呼ばれる一群の怪しげな変数があります.$. とか $& とか @_ などなど.あらかじめ何らかの値をセットしてあって特定用途に使われたり, 特定の処理をするとその副作用として値がセットされたりする変数です. そのなかの $_ はよく使われます.

ファイルを一行づつ読むために,while ($line = <>) {} とか, while ($line = <FILE>) {} といった文を何度も書きました. このように while 文の () のなかに入力演算子 <> を書いたときに限り, $line = <> のように代入の式を書かなくともよい,その場合,読み込んだ内容は $_ という名前の特殊変数にしまわれる,というルールがあります. さらに,いくつかの関数は,とくに引数を指定しないと $_ を処理するようになってます. chomp, split はいずれもそうです.そこで,

while ($line = <>) {
    chomp $line;             # $line の末尾の改行コードを削除
    next if ($line eq "");   # 空白行だったらあとの処理はせずに次を読む.
    ($x, $y) = split /\s+/, $line;
    print $x, "\t", $y, "\n";
}

は次のように書いてもまったく同じように動作します.

while (<>) {
    chomp;                 # $_ の末尾の改行コードを削除
    next if ($_ eq "");    # 空白行だったらあとの処理はせずに次を読む.
    ($x, $y) = split /\s+/;
    print $x, "\t", $y, "\n";
}

foreach 文でも,$_ を使うことができます.foreach の直後に書くと, リストの各要素の別名となる変数名は省略できて, $_ が別名となります.

foreach $species (keys %count) {
    print $species, "\t", $count{$species}, "\n";
}

は次のように書いてもまったく同じように動作します.

foreach (keys %count) {
    print $_, "\t", $count{$_}, "\n";
}

このほうが書く手間は少し減りますが,読みやすくなるとは限りません. $species のような意味のある変数名を書いておくと,キーになる文字列は なにを表すものかがはっきり分かるというメリットがあります.

前後関係,プログラムの長さ,あとあと使うか使い捨てかなどを 考慮して,どのぐらい楽をするかを決めます.


砂糖の量はお好みで

Perl の標語は "There's More Than One Way To Do It." です. 唯一の正しい書き方があるわけではない,自分のやりたいことができればそれでいい, という考え方です.

上に紹介したほかにもいろいろ syntactic sugar はあります. 使いたければ使う,趣味じゃないと思えば使わない,どちらでもけっこうです.



| Top Page | プログラミング | Perl 目次 | prev | next |