Daysこの広告は、90日以上更新していないブログに表示しています。)はじめに今回のネタは,Clojureのパターンマッチライブラリであるcore.matchです。パターンマッチは,Lispのマクロの応用的な例として本などのネタで取り上げられることが多いですが,データ構造によって処理を分岐したり,複雑なデータの中から一部を取り出す場合などに実際に使える便利な機能です。今回はこのcore.matchを使って型システム入門の3,4章に出てくる算術式のインタプリタを実装します。core.matchを使用する場合には,Leiningenのproject.cljに以下を追加する必要があります。2013年12月現在の最新版は0.2.0-rc6です。"0.2.0-rc6"]パターンマッチcore.matchでは,matchというパターンマッチマクロが提供されています。matchマクロの構文はこのようになっています。満たすかどうかを確かめます。満たす場合,が実行されます。満たすかどうかを試します。以降同様に,マッチするパターンが見つかるまで順にパターンが試されます。すべてのパターンにマッチしなかった場合には,:else節に記述されたが実行されます。:else節は省略することもできますが,その際にはマッチするパターンが見つからなかった場合に例外が投げられます。実際にmatchマクロを使ってみましょう。以下はmatchを使ったFizzBuzzの例です。:fizzbuzz)user=>ベクタのパターンマッチは単純です。マップのパターンマッチは,パターンに指定したキーのみに対してパターンにマッチするかどうかが確かめられます。そのため,パターンに現れないキーをマップが持っていることはパターンにマッチするかどうかに影響を与えません。:seq)で囲んでやる必要があります。)はパターン内でリストやシーケンスを表すパターンとしては扱われず,:seqや(ここでは詳しく触れませんが)ガードやアズパターンなどの特殊なパターンで使われるので注意が必要です。]を省略することができます。上のシーケンスのパターンマッチの例は以下のようにも書けます。:a2)この他にもさまざまなパターンが用意されていますが,詳しくはcore.matchのWikiを見るのがいいでしょう。算術式インタプリタの実装さて,それではcore.matchの応用例として,型システム入門の3,4章に出てくる算術式のインタプリタを実装してみましょう。ここで扱う算術式の項は以下のとおり。)この算術式の各項の大まかな振る舞いは次のとおり。t)はtの前者値を返す。tが0の場合は0を返す。t3)はt1がtrueの場合にt2の評価結果を返し,falseの場合にt3の評価結果を返すこの算術式のインタプリタを,core.matchを使って実装したのが以下のコードです*1。(recur))))実行例はこんな感じになります。おわりに今回はcore.matchによるパターンマッチを紹介しました。パターンマッチを使うと,コードの見通しがよくなることもあるので,使える場面では積極的に使ってみたい機能です。パターンマッチの実装についても,以下のような文献を参考に効率的な実装になっています。core.matchの実装について興味があれば参照してみるのもいいでしょう。Dispatch次回は,引き続きathosがtools.loggingについて書きます。*1:このコードは型システム入門4章に掲載されているOCamlのコードをそのままClojureに翻訳した形になっています。Clojureとして,特にこのような例外の使い方が推奨されているわけではありません。