TAKESAKOさんの ppencode が何で動くのか分かった。
かなり古い話題かもしれませんが,ppencode の動作原理が分かったのでその感動を日記に記します。
僕は半年前ほど前からperlの勉強を始めましたが,始めてまだ間もない頃にppencodeを知って,これが何故動くのかが当時は全然分かりませんでした。
ppencodeって何?って方は下記URLを参照すると,分かります。’予約語プログラミング’なんてキーワードでググってみても関連情報が出てきます。
TAKESAKOさんのサイトでppencodeのデモが見れる
http://www.namazu.org/~takesako/ppencode/demo.html
id:naoyaさんのブログエントリ
http://d.hatena.ne.jp/naoya/20050901/1125556355
上述したTAKESAKOさんのデモページで'test'の文字列を入れるとですね・・下記のようなppencodeに変換されます。
#!/usr/bin/perl -w length q rmdir and print chr ord q stat s and print chr ord q ge log and print chr ord q msgctl m and print chr ord q stat s
このコードを実行すると,ちゃんと'test'と表示されます。で,何でこんなコードが動くのかと言うと・・。
まず,このままだと分かりにくいのでコードを分解します。
#!/usr/bin/perl -w
length q cmp lc
and
print chr ord q stat s
and
print chr ord q ge log
and
print chr ord q msgctl m
and
print chr ord q stat s
赤字のところが実際に't'や'e','s','t'を表示する文です。例に4行目の't'をprintする文を見てみましょう。
例:print chr ord q stat s
1. これは,q stat s の部分がミソで,qs 〜 sでクオートされた'tat 'という文字列を意味します。
2. 'tat 'を ord に渡してやると,ord は't'のASCII値を返してくれます。
3. 't'のASCII値を chr に渡すと,文字列't'が返ってきます(!)
4. 't'を print します。
1の部分がミソで,3の部分でトリックの謎が解けた感じですね。'q stat s'がクオートだということが分かれば,あとはord→chrで「な〜んだ」というくらい簡単な処理をしているだけです。もう一つ別の行を見てみましょう。今度は先ほどよりも早く何を表示する行か分かるはずです。なぜなら,クオートされた文字列の先頭文字を見れば良いからです。
例:print chr ord q msgctl m
この文は's'を表示します。qm〜mとなっていることが分かりますでしょうか?
分かってみると何でもないかもしれませんが,文字だけの予約語を巧みに使った面白いトリックだと思います。substrで文字列の先頭文字を取ろうとすると,数字を使わなきゃいけないところが,ord → chr をすれば文字列だけで出来るなんて!
masutaro を変換すると,こんなppencodeが表示されます。
#!/usr/bin/perl -w
length q caller getc and print chr ord qw q m q and print chr ord q map m and print chr ord q msgctl m and print chr ord q dump and and print chr ord q stat s and print chr ord q each ne and print chr ord q qr eq and print chr ord q pop
パッと見ただけじゃ何が書いてあるのか分からないですよねw
初めて見た人に,「なんじゃこれーー!」「何でこれが動くの!?」っていう驚きを与えられるところが,ppencodeの面白いところだと思います^^
このppencode,漢字もできますが,漢字は単純に’あ’を変換しただけでも出力されるコードが,英語に比べて少し長いようです。
chr hex という部分がありますが,どうやらここがミソっぽいですね。また時間のあるときにでも見てみようと思います。
あ,あとちなみに変換後のコードの最初(#!/usr/bin/perl -wは除く)はいつも length〜ってので始まります。これを解釈すると,
length q cmp lc and
qc〜c だから・・,'mp l'を length に渡していることが分かります。
後の処理を and で続けていますが,ここでperlのバージョンチェックをしているのでしょうかね。なくても動きます。それとも見た人を,かく乱させるためのダミーでしょうか??