基本的な制御構文の紹介

この記事はPerl6 Advent Calendar 2011の3日目です。


今年は誰も名乗りを上げないようなので、私が勝手にPerl6 Advent Calendarを立ててしまいました。まだまだ参加者募集中なので、我こそは!という方は是非ATNDに登録をお願いします。


前回はぜっぱち(@Zeppachi)さんによるPerl6の紹介でしたので、私もそれに続こうと思います。この記事のテーマは「制御構文」ということで、Perl6における一般的な制御構文を、Perl5と比較しながら紹介して行きましょう。


また、この記事の内容は締切がやばい解りやすさを優先したい等の理由から、あまり厳密でない説明が多分に含まれます。詳しく知りたい方は、一日目の記事でも紹介されていましたがPerl6の仕様であるSynopsisのBlocks and Statementsを参照してください。

if/unless

Perl6の条件分岐はPerl5のそれと殆ど変わりません。ifの直後に来る条件節を評価して、真であれば続くブロックを実行します。elseやelsifについても同じです。違う点を上げるとすれば、条件節を囲む丸括弧が必要無くなったくらいでしょうか。
注意すべき点としては、ブロックを始める中括弧を条件節に隣接して書かない点でしょうか。他の構文にもいえる事ですが、中括弧の直前はスペースを空けないと、ハッシュへのアクセスだと解釈されてしまいます。

if $cond_1 {
   # $cond_1 => True
} elsif $cond_2 {
   # $cond_1 => False && $cond_2 => True
} else {
   # それ以外
}

loop

C言語スタイル(3-part spec)のfor文を書くための構文です。Perl5ではfor/foreachを使っていましたが、Perl6ではfor文の機能が拡張されるに従い、loop分に分離される事になりました。条件節の丸括弧は省略できません。

loop ($i = 0; $i =< 10; $i++ ) {
     # $iを0から10までインクリメントしながらブロックを実行
}

loop (;;) {
     # 無限ループ
}

while/until

条件節が真/偽である間、後ろに続くブロックを繰り返し実行します。Perl5ではwhile/untilを後置する際にdo文を使っていましたが、Perl6ではrepeatに変更されました。これは、Perl6のコードをより英語的な言い回しに近づけるための配慮(?)だそうです。条件節の丸括弧は省略できます。

while $i < 0 {
      # $iが0未満の際に処理を継続
}

repeat {
       # 後置する場合はrepeatを使用
} while $i < 0;

repeat while $i < 0 {
       # 後置whileと等価なので注意
}

for

for文はデータの集合に対してイテレートを行う文法です。先にも述べた通り、Perl6でのfor文はかなり強力な構文になっています。forに続けて配列やリストなどを記述すると、各要素が先頭から順に$_にコピーされ、ブロックの内容が実行され、要素が無くなると繰り返しを終了します。

for @list {
    # @listの要素が先頭から$_にコピーされて実行される
}

for 1,2,3 {
    # リストを直接書いたりも出来る
}

for %hash {
    # forにハッシュを渡すと、keyとvalueのPairが$_にコピーされる
}


また、pointy blockという記法を使う事で、$_ではなく明示的に名前を付けた変数に値をコピーできます。矢印の右側に複数の変数を記述する事で、その個数ずつ取り出す事も出来ます。この時、ループの最後で取り出す個数が足りないとエラーになるので注意しましょう。このpointy blockは関数の定義の類なので、関数のシグネチャに書ける値の制約やデフォルト値なども記述できます。

for @list -> $element {
    # $elementに要素が順にコピーされる
}

for @list -> $element is rw {
    # 配列の要素を直接変更したい場合は"is rw"を指定する
}

for @list <-> $element {
    # 上と等価
}

for @list -> $a, $b {
    # 先頭から2つずつ要素を取り出すことも可能
}

for 1,2,3, -> $a, $b {
    # リストが奇数個なので失敗する
}

for 1,2,3 -> $a, $b? {
    # 後ろの変数に省略可能(optional)を指定すると、要素が足りなかったときは$bにMuが入る
}


ハッシュにはkeyとvalueを交互に返すkvメソッドが用意されており、for文と組み合わせる事で簡単に処理できます。

for %hash.kv -> $key, $value {
    # keyとvalueがそれぞれ$keyと$valueにコピーされる
}


また、Zオペレータと組み合わせる事で、複数の配列を先頭から舐めて処理するような事も出来ます。

for @a Z @b -> $elem_a, $elem_b {
    # $elem_aには@aの要素が、$elem_bには@bの要素が順にコピーされる
}


またRangeを与える事で、ループを特定の回数繰り返すような使い方もできます。

for 0..10 {
    # 0から10まで$_にコピーしながら11回繰り返す
}

for 0..^10 {
    # 0から(10-1)=9まで$_にコピーしながら10回繰り返す
}

for ^10 {
    # 上の省略表記
}


もちろん後置する事も出来ます。

{ ... } for @list;

.say for @list;
# 後置の場合は、処理が1ステートメントなら中括弧も省略可能

まとめ

これでPerl6の基本的な制御構文は一通り紹介し終えました。じつは他にも載せきれなかった構文が幾つもあるのですが、もしかするとこれからの記事で出てくるかもしれませんね。もちろん今日紹介した構文は何度も出てくると思いますので、これからの記事を読む助けになれば幸いです。