前置き
昨日、DentooLT #7に行ってきました。面白いLTばかりで楽しかったです。
そこで、RubyでQuineを書いたってLTを見ました(Slideshareとかに上がってないのかな…)。
クワイン(英: Quine)は、コンピュータプログラムの一種で、自身のソースコードと完全に同じ文字列を出力するプログラムである。
ものすごく簡単なQuineをRubyで書くと、こんな感じです。
quine.rb
puts File::open(__FILE__).read
$ ruby quine.rb puts File::open(__FILE__).read
__FILE__
で自身のパスが取得できるので、自分自身が標準出力に表示されています。
ところで、rubyインタプリタはスクリプトファイルを与えなければ標準入力をRubyスクリプトとみなして実行されます。
ここで、option は後述のコマンドラインオプション のいずれかを指定します。-- は、オプション列の終りを明示するため に使用できます。programfile は、Ruby スクリプトを記述したファイ ルです。これを省略したり`-' を指定した場合には標準入力を Ruby ス クリプトとみなします。
つまり、下のようなことが出来ます。
$ cat quine.rb | ruby puts File::open(__FILE__).read
ここで、quine.rbは自身を出力するのでした。そのため、次のようなことが可能です。
$ ruby quine.rb | ruby puts File::open(__FILE__).read $ ruby quine.rb | ruby | ruby | ruby | ruby | ruby | ruby | ruby | ruby | ruby puts File::open(__FILE__).read
...ってことをLTで聞いて、その発想はなかったなーと思いました。
本題
ということで、階乗を計算するQuine(もどき)を書きました。
Usage
Ruby をパイプでつないだ数の階乗を計算します。
$ ruby quine.rb 1 $ ruby quine.rb | ruby | ruby 6 $ ruby quine.rb | ruby | ruby | ruby | ruby 120
しくみ
単純に、パイプをつなぐ度にインクリメントしているだけです。
IO#tty?
でパイプが途切れたのを判定し結果を計算し出力します。
最後にcat
をパイプでつないでやれば、Quineもどきが出力されているのがわかると思います。
環境変数とか使えたら、完全にQuineにできたんだけどなぁ…。
ファイルを使うのは気持ち悪いと思った。