こないだの RHG 読書会で、 Ruby プログラムのインストールイメージに関する話題があった。 よーするに、setup.rb の要求するディレクトリツリーが 非人道的で有罪でインタプリタの利点をスポイルしてしまうという話だ。 なんでかって言うと、ユーザが自分でライブラリを編集したいと思った場合、 毎回インストールしないと変更が反映されないから。
それでは自分の場合はどうかというと、 いちいちインストールするのはうざいのでシンボリックリンクを作ってるんだな。 こういうふうに。
~/lib/ruby/refe@ -> ~/c/refe/lib/refe ~/lib/ruby/tmail@ -> ~/c/tmail/lib/tmail ~/lib/ruby/racc@ -> ~/c/racc/lib/racc ~/lib/ruby/amstd@ -> ~/c/amstd/lib/amstd ~/lib/rubyext/tmail@ -> ~/c/tmail/ext/tmail
これで ~/lib/ruby と ~/lib/rubyext を $RUBYLIB に入れとく。 これで常に変更が反映するというわけだ (その代わり、何を使っても必ず最新版が動いてしまうという不便さもある)。
で、この作業をユーザにも強いるのか、極悪だダメダメだ非人道的だと言われたので、 それじゃあこれがだめならどーするんだ対案を出せと小一時間問い詰め^H^H^H^H みんなの協力のもとに検討したところ、次のような案が出た。
bin/refe bin/mkrefe_rubyrefm refe/database.rb # ライブラリ refe/..... test/test*.rb
つまり、Ruby のライブラリパスにカレントディレクトリが入ってるんだから それをベースに考えようってことだな。 bin が残っているのは、bin/refe と refe/ が衝突するということが判明したから。
しかしこの方法にもいくつか欠点がある。
あと、setup.rb フォーマットのほうがいいと思った点が、
というところだと思う。たとえば lib/ に入ってれば、 ああこれはライブラリだな、と、すぐに (ディレクトリ構造を見ただけで) わかる。 他人の作ったプログラムをいじるときには まずファイルの役割がわからないとあたりがつけられないので、 ファイルの属性がはっきりわかるというのは重要だと思う。 つまり、必ずしも編集のしやすさだけが変更のしやすさを示すのではないと言いたい。
インストーラに関しては、 そもそもインストーラがいらんという話もあったな。 適当に require を検出して展開しファイル一つにしてしまえば cp だけで済む。 ライブラリも zip なり ar なりで提供できるようにすればよい (ruby のほうを改造してしまえばよい)。という感じだったと思う。
でも改めて考えると ReFe のデータベースがインストールできないな。
ついでに言えば、ファイル融合をやるためには ライセンスを統一しとかないとまずそうだよな。 require ならなんとなく灰色で済ませるんだが。
結論としては、「やっぱり俺は setup.rb でいいや。」ということで。
ところで、setup.rb はでかすぎるような気がする。 「インストールするライブラリより setup.rb のほうがデカい」 とか言われると悲しいものだ。 機能を絞ってもっと小さくできないのだろうか。
結論から言うと、たぶん無理だな。
だってさー、なんだかんだ言ってルートディレクトリだけ すりかえてインストールとかしたいでしょ? config オプションが減るのは不便でしょ?
よろしい、ならば setup.rb だ。
……なんでコピペに移行するかな。
x と y が互いに素であるか判定するプログラム。 型を付けて引用するとこうなる。
ss :: [[Bool]] ss = map s [0..] s :: Int -> [Bool] s 0 = cycle [False] s 1 = cycle [True] s n = cycle $ map (!! n) $ take n ss
(ss !! x) !! y で、x と y が互いに素かどうか判定できるらしい。 「!!」は Ruby で言う ary[i] みたいなもんだ。
うーん。仕組みが全然わからないよ……。
それはともあれ、モナドとモナコは似てないこともない。
追記: いや、さすがに Bool の二次元配列になってるとこまではわかるんですが、 その表がどういう理屈でどういう構造 (配置) になってるのかがわからないのです。 無限リストだと簡単に表示するというわけにもいかないし。
と愚痴ってるあいだに表示してみよう。 とりあえず 8 × 8 くらい表示すればいいかな。
*Tmp> map ((ss !! 0) !!) [0..7] [False,False,False,False,False,False,False,False] *Tmp> map ((ss !! 1) !!) [0..7] [True,True,True,True,True,True,True,True] *Tmp> map ((ss !! 2) !!) [0..7] [False,True,False,True,False,True,False,True] *Tmp> map ((ss !! 3) !!) [0..7] [False,True,True,False,True,True,False,True] *Tmp> map ((ss !! 4) !!) [0..7] [False,True,False,True,False,True,False,True] *Tmp> map ((ss !! 5) !!) [0..7] [False,True,True,True,True,False,True,True] *Tmp> map ((ss !! 6) !!) [0..7] [False,True,False,False,False,True,False,True] *Tmp> map ((ss !! 7) !!) [0..7] [False,True,True,True,True,True,True,False]
頭の悪い方法だが、見やすいからいいとしよう。 もうちょい整形するとこうなる。
[False False False False False False False False] [True True True True True True True True] [False True False True False True False True] [False True True False True True False True] [False True False True False True False True] [False True True True True False True True] [False True False False False True False True] [False True True True True True True False]
(0,1) 以外は線対称かな。線対称ですね。
いやでもやっぱ結果だけ表示してもわからないな。 どうなったら理解したと言えるんだろう。
追記 2: しつこく ss を見やすくしてみる。
- - - - - - - - o o o o o o o o - o - o - o - o - o o - o o - o - o - o - o - o - o o o o - o o - o - - - o - o - o o o o o o -
「互いに素」マップ (640 × 640)
前項の ss をビットマップにしてみた。 True が #1f7f1f、False が #cfcf00。 このビットマップを作るスクリプトもいちおう以下のとこに置いておく。
Copyright (c) 2002-2007 青木峰郎 / Minero Aoki. All rights reserved.
setup.rb.petite ぶちっと減ったってことですね。
ssは2次元の表ですな。
http://www.sampou.org/cgi-bin/cahier.cgi?Cahier%3a2004-01-02&l=jp とか。
ありがとうございます。リンク張り直しました。
あけましておめでとうござます。
面白いです。数学的な内容はユークリッドの互除法ですね。
mprime :: Int -> Int -> Bool
mprime _ 0 = False
mprime _ 1 = True
mprime m n = mprime n (mod m n)
みたいな感じで、
ss = [[mprime i j | i <- [0..]] | j <- [0..]]
なるほど、ユークリッドの互除法ですか。
そう考えたらなんとなくわかってきました。
ありがとうございます。