From: keiju / rational.com (石塚圭樹 )
Subject: [ruby-list:6479] Re: call for scripts 
Date: Tue, 17 Feb 1998 23:02:54 +0900
Message-ID: <199802171318.WAA02938.keiju / bc.mbn.or.jp>
keiju> あと,
keiju> 
keiju> 3. パズル関係のプログラム
keiju> 4. パズル的なプログラム
keiju> 5. メソッドの連鎖がナガーク続くプログラム
keiju> 
keiju> なども, 採用される確立が高いと思います(ただし, 本文というかコラム扱い
keiju> になると思いますが(^^;;;). この分野にお強い方も多いみたいですので, 興
keiju> 味ある方は挑戦してみて下さいませ(__;;;


千田@リコーと申します。


サイン本ほしさにちょっと作ってみました。


いわゆる自己再生プログラムというやつです。
プログラムの実行結果が自分のソースコードとなるようなプログラムのことで

	% ruby xxx.rb | diff -c - xxx.rb

が何も出力を返さないようなプログラムxxx.rbのことをいいます。

C言語では

main(a){printf(a,34,a="main(a){printf(a,34,a=%c%s%c,34);}",34);}

がよく知られています。

これをまねしてrubyで書くと
(1)---------
#!/usr/local/bin/ruby
a='#!/usr/local/bin/ruby
a=%c%s%c;printf(a,39,a,39);
';printf(a,39,a,39);
------------
というぐあいになります。

# 最初Cと同じ構造にしようとしたらrubyでは引数の評価 -> 関数引数のbindの
# 関係がCと違うことに気づいてしまった。printf(a,...)のaのところで
#    undefined local variable or method `a'
# となってしまう。

これじゃああんまりおもしろくないので
  (1) printfを使わないで
  (2) ruby特有の機能を使って
  (3) 文字コードを仮定しないで(上の39は"を意味している)
出きるようなものを書いてみました。

(2)---------
#!/usr/local/bin/ruby
def once;yield"end;once{|x,y|print y;print x.inspect,',';p y;print x+'\n';}","#!/usr/local/bin/ruby\ndef once;yield"
end;once{|x,y|print y;print x.inspect,',';p y;print x+'
';}
------------ (注:2行目は長いのでmailでは折り返されてしまうかも知れない)

これでは何のことかわからないので解説しましょう。:-)
うえの(2)の中の自己言及している文字列を短く置き換えると

(2')---------
#!/usr/local/bin/ruby
def once;yield"xxx","yyy"
end;once{|x,y|print y;print x.inspect,',';p y;print x+'
';}
------------

となり(これならよめるでしょう)、実行結果は

yyy"xxx","yyy"
xxx

となります。iteratorの定義で文字列を定義し、実行部分でもとのソースコードと
相似な形に出力するように出力部を調整しているだけです。文字列に対する
inspectが""をつけて返してくれるおかげでこの部分はきれいに書けます。


上の2つは"まじめ"な方法で実現したものですが、実は"ふざけた"方法で自己再生
プログラムを作ることができます。
それは、、、

(3)--------- #!/usr/local/bin/ruby a=open($0,"r") while a.gets print $_ end ------------ # 飛び道具攻撃 !! 説明は不要でしょう。 :-) では。 --- +--------------------------------------------------------------------+ | (株)リコー SS事業本部 周辺機器開発部 開発2グループ | | 千田滋也 (senda / ic.rdc.ricoh.co.jp) | +--------------------------------------------------------------------+