このブログの更新は Twitterアカウント @m_hiyama で通知されます。
Follow @m_hiyama

メールでのご連絡は hiyama{at}chimaira{dot}org まで。

はじめてのメールはスパムと判定されることがあります。最初は、信頼されているドメインから差し障りのない文面を送っていただけると、スパムと判定されにくいと思います。

参照用 記事

CatyScriptで無限に動き続けるFizzBuzzが書けた

今年(2011年)の8月末に「1年たって、手書きから自動描画へ」という記事を書きました。タイトルのとおり、1年前の構想がなんとか形になってきたことの報告です。

1年前どころか、2年以上も前の2009年10月の記事「フローチャートからマゾ・テストまで」では、マゾ・テストの構想を述べています。「マゾ・テスト」って呼び方はアンマリなんで、最近はインスタントファジングと呼ぶことにしています。「WebアプリケーションフレームワークCatyの現状と今後」で紹介した100倍速プロトタイプングである「インスタントモックアップ」とペアになる概念です。

インスタントファジングを行うには、CatyScriptを無限に(実際は非常に長い時間)走らせる必要があります。そもそも、インタプリタのトップレベルループ(REPL)を書くにも無限ループが必要です。無限ループ構文にはbegin/repeatを予定しています。そのことは、やはり1年ほど前の記事「CatyScriptで記述するCatyシェル」で書いています。

その頃(2010年11月)は無限ループはできなかったので、机上の(あるいは脳内の)コードを「無限FizzBuzzをCatyスクリプトで書いてみる」にメモしておきました。

さて、実はbegin/repeatはまだ出来てません。でも、begin/repeatと同じことができるforwardという制御構造は既に動きます。forwardを使って無限に動き続けるFizzBuzzを書いてみました。


// -*- coding: utf-8 -*-
/** FizzBuzz
* see [[http://d.hatena.ne.jp/m-hiyama-memo/20101109/1289265674 ]].
*/
module fb;

/** 入力を1増やして出力する */
command inc :: integer -> integer
refers python:fb.Inc;

/** 入力が、引数で指定された数で割り切れるかどうかを判定する */
command dividable-by [integer] :: integer -> (@True integer | @False integer)
refers python:fb.Dividable;

/** coutの代替、入力に number も可能 */
command say :: number | string -> void
refers python:fb.Say;


/** 入力値を開始の数として、FizzBuzzを永遠に続ける。
* 出力を生成することはないので、出力の型はneverである。
*/
command forever :: integer -> never {
pass > in | dividable-by 15 |
when {
True => ("Fizz Buzz" | cout), // 15の倍数
False => dividable-by 3 |
when {
True => ("Fizz" | cout), // 3の倍数
False => dividable-by 5 |
when {
True => ("Buzz" | cout), // 5の倍数
False => fb:say, // その他
}
}
};
sleep 200;
%in | inc | forward fb:forever
};

/** FizzBuzz forever その2
*/
command forever2 :: integer -> never {
dividable-by 15 |
when {
True => [pass, ("Fizz Buzz" | cout)] | nth 1, // 15の倍数
False => dividable-by 3 |
when {
True => [pass, ("Fizz" | cout)] | nth 1, // 3の倍数
False => dividable-by 5 |
when {
True => [pass, ("Buzz" | cout)] | nth 1, // 5の倍数
False => [pass, fb:say ] | nth 1, // その他
}
}
} | sleep 200 | inc | forward fb:forever2
};

基本コマンドを記述したPythonコードの部分は「無限FizzBuzzをCatyスクリプトで書いてみる」とまったく同じなので省略します。

foreverコマンドは、inという変数への代入(> in )と参照(%in)を使っています。2010年に書いた机上コードでは変数を使っていません。当時はまだ変数機能を入れてなかったせいかな? forever2のほうは2010年版変数なしのスクリプトです(今は動きます)。がんばれば変数が要らないこともCatyScriptの特徴なので、変数なしのバージョンも載せておきました。

実行すると次のようになります。


caty:sample> 1 | fb:forever
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
Fizz Buzz
16
17
Fizz
19
Buzz
Fizz
22

無限ループ(長時間の繰り返し)ができるようになって、マゾ・テスト改めインスタントファジングに少し近付いたと思います。