よたらぼ
自分の興味の赴くままにIT技術系のネタを取りとめもなくメモっています。
Ruby言語やLinuxのネタが多いです。

March 31, 2002

[tDiary] fortune.rb

kjanaさん、ZnZさん、どうもです。こんなコードでしょうか?

イマイチエレガントに書けない....。っつーか、まだ間違えてたりして(^^;)。

s = Time.new
def fortune(file)
  res = ""
  line = ""
  IO.readlines(file, "\n%\n").each do |line|
    res = line if rand($.) < 1
  end
  res = line if res == ""
  res = $2 if res =~ /^(%\n)?(.*)\n%\s*\n?$/m
  res
end
 
puts  fortune(ARGV[0])         #(1)
 
#(0..1000).each { fortune(ARGV[0]) }
#p Time.new - s

2つ実装ができたので、どっちが速いのかなぁというわけで時間を図ってみることに(上記のコードの#の部分を有効にして(1)をコメント化)。ascii-artというfortune辞書を10倍にしたファイルを作ってみた。

$ruby test.rb ascii-art-10-times.txt
6.033442

対するは、今のfortuneのコードの簡略化版

s = Time.new
def fortune(path)
  open(path) do |file|
    lines = file.read.split(/%\n/)
    lines[rand(lines.size)]
  end
end
 
(0..1000).each { fortune(ARGV[0]) }
 
p Time.new - s

んで、結果。

$ruby fortune-lite.rb ascii-art-10-times.txt
1.542972

あり?今のコードの方が速い....。なんか間違ってんのかな? 

教えていただいたコードって、rand($.)でマッチしてもbreakしたらダメなんですよね?

うーむ...。どうも、IO.readlines()が遅いみたい。以下のコードを試してみる。

s = Time.new
def fortune(file)
  IO.readlines(file, "\n%\n").each do |line|
  end
end
(0..1000).each { fortune(ARGV[0]) }
p Time.new - s
$ruby test2.rb ascii-art-10-times.txt
5.926064

考えてみたらあり得ない結果とはいえなくもない気がしないでもない(ってどっちだ?(^^;))。ARGF.getsだともうちょっと速いのかな?

s = Time.new
def fortune(file)
  ARGF.each do |line|
  end
end
 
(0..1000).each { fortune(ARGV[0]) }
p Time.new - s

あり?これ、1回、ARGFがEOFまで読み込まれた後、反応しなくなってしまう。なんでだろう。そういうモノなのかな? ま、いっか。疲れたし(^^;)。

おっと、忘れてた。オレの環境はLinux-2.4.18 / ruby 1.7.2 (2002-01-05)[i686-linux]、試したfortune辞書のサイズは59040byte, 1540行だ。

ちなみに、いろいろやっている間、先頭が%から始まるfortune辞書では、空文字が返されるバグを見つけた。明日にでも直すか...。

本日のツッコミ(全4件) [ツッコミを入れる]

Before...

恵司 [XREA + tDiary + Namazuのマニュアルにある.namazurcの編集の編集ですが Replace..]

kjana [ > ruby -v ruby 1.6.5 (2001-09-19) [sparc-solaris2...]

むとぽん [kjanaさん:追試どうもです。今回はメモリのサイズも気にするほどでもないと思いますので、前のアイデアのままで行こう..]


March 31, 2003

[Hiki] Hiki/RD+-0.1.3

さっそくバグってました。こっち使ってください。てへっ。

本日のツッコミ(全2件) [ツッコミを入れる]

(う) [Hiki/RD+ですが、ModulesNamesというページがない(初期状態)か、ModuleNamesというページ..]

むとぽん [うげっ、すみません。 とりあえず、ModuleNamesにGtkとでも書いてdata/text/配下に置いてください..]


March 31, 2005

[Ruby] Using Gettext To Translate Your Rails Application

著者のSascha Ebachさんから、こんなん作ったよ、どう?というメールが来たので読んでみた。Ruby on RailsでRuby-GetText-Packageを使おうてな話。

よくできてるとは思うけど、このまま一般的なフレームワークとして推奨するとしたら、相当制限がきついと思う。というのも、gettext本体に手を入れて「全てのスクリプトが扱うメッセージカタログ(moファイル)は一つしかない(以降案1)」という前提にしているから。

Ruby-GetText-Packageでは、1つのスクリプトごとに1つのメッセージカタログ(moファイル)をバインド(bindtextdomain)するようにしている(以降案2)。

最初は、1クラス単位、モジュール単位、といったことも考えたのだが、Rubyのように既存クラス・モジュールに、後から別の機能を追加できるようなものを前提とすると、ファイル単位にメッセージカタログを持たせるのが一番現実的だと判断したからだ。なので、1つのスクリプトファイル中で1回は「bindtextdomain」を呼ばないといけない。もちろん、実装上は、同じメッセージカタログ名であれば使い回すという風にしているため、通常のアプリケーションであればせいぜい1、2個のメッセージカタログを複数のスクリプトから参照するということなので、ファイルを読み込む処理とかメッセージカタログが占めるメモリ使用量といったところで激しく性能劣化が出ないようにしている(つもり)。

で、案1にしてしまうと、すぐに問題として思いつくのが、BBSとBLOGの2つの機能を持ったアプリを作る場合でもメッセージカタログを1つにしないといけない、ということだ。プラグインのような機能もメッセージカタログはパッチで提供する形になってしまう。これはイケテナイ。

もう一つ、Ruby-GetText-Packageを使った他のライブラリ等が使えなくなってしまう(厳密にはローカライズされずに英語で表示されてしまう可能性が高い)。現状、そのようなライブラリは存在しないと思うのでちょっと杞憂すぎるかもしれないけど。

案2の問題点として、Saschaさんが指摘してるのは、毎ファイルごとに宣言するやり方はDRY(Don't Repeat Yourself)の法則に反する、このようなものは1カ所で宣言したいというものだ。

気持ちは分からないでもないが、案1の問題がクリアできない以上、共通的なフレームワークとして採用するのは厳しいと思う。

もちろん、Saschaさんの指摘をクリアできるような何か良いアイデアがあるといいのだけど...。

RoR界隈では、他にもYAML/XMLを使った独自実装のアイデアも出てるらしいけど、言語リソースは(特に頻繁に変更があるようなアプリケーションでは)、GetTextが提供している各種ツールのようなメンテナンス用のツールが充実していないとメンテが大変になるので、そういったものが用意できない場合はGetTextを使った方が良いような気もする。

対象となる文字列が少ない場合は、もっとライトウェイトにHikiやtDiaryが使っているメソッドや変数に言語リソースを設定するやり方も良いと思うけど、RoR界隈でその辺の実装をチェックしてる人はいないのかなぁ。

ちなみに、彼が改造したRuby-GetText-Pacakgeのいくつかは今回の指摘箇所以外ということでも有用だったのでその部分はいただくこととしよう。


更新 設定