帝力何有於我哉

無職。汎用人型雑用兵器。型式番号: 高木 宏 ( Hiroshi Takagi )

Re: 【だいたいあってる時計】乱数の代わりに配列をつかってみたよ

kondoyuko さんのRuby修行のフォローです

id:kondoyuko:20110111:1294754578 で書かれているプログラムへのコメントです。
(はてなDiary のコメント内にはてな記法を使う方法がようわからんかった orz

作ろうとされている辻褄時計の目指しているものがいまいちつかめていない(というか経緯を知らない)ので、プログラムのお作法的なところでいくつかアドバイスを。

オブジェクト名と collect メソッド

ary = []
for i in 0..20
  ary << 0.1 * i
end

まず、ary っていうオブジェクト名(変数名)は、"配列"ということを意味しているんだろうけど、この場合は、"時計がどれだけ狂う(drift)するかの秒数のテーブル"ということのようだから、clock_drifts とでもしてみましょうか。
プログラムでは、オブジェクト名、メソッド名にわかりやすいものをつけて行く習慣がとてもだいじです。ima の方はとてもわかりやすいw

次に 0..20 という範囲オブジェクト(Rangeクラスのオブジェクト)は、Enumerableモジュールをインクルードしているので、配列オブジェクトと同じように collect という便利なイテレータメソッドが使えます。
以下、irb で示します。

irb(main):021:0> (0..5)
=> 0..5
irb(main):022:0> (0..5).class
=> Range
irb(main):023:0> (0..5).to_a
=> [0, 1, 2, 3, 4, 5]
irb(main):024:0> (0..5).collect{|i| i* 0.1 }
=> [0.0, 0.1, 0.2, 0.3, 0.4, 0.5]
irb(main):025:0> a = (0..5).collect{|i| i* 0.1 }
=> [0.0, 0.1, 0.2, 0.3, 0.4, 0.5]
irb(main):026:0> a
=> [0.0, 0.1, 0.2, 0.3, 0.4, 0.5]
irb(main):027:0> a.class
=> Array

つまり、clock_drifts は、以下のように一行で定義できます。

clock_drifts = (0..20).collect{|i| i* 0.1 }

ちょっとクラスプログラミング風に

わたしが同じものを書くとたぶんこうなるだろうというものを。
loop 周りはちょっと動作を変えました start_ticking すると、
すぐに現在時刻を表示して無限ループに入ります。

class TsujitsumaClock
  CLOCK_DRIFTS = (0..20).collect{|i| i* 0.1 }

  def self.sleep_random
    sleep(CLOCK_DRIFTS.choice)
  end

  def self.start_ticking
    ima = Time.now
    loop do
      puts ima
      ima += 1
      self.sleep_random
    end
  end
end

TsujitsumaClock.start_ticking

ちょっとしたロジックでも名前をつけてメソッドにする習慣をつけておくと、見通しがよくなり、テストや評価も楽です。
> 結果、よく解らん!!!あんまり変わんないような気がする。
と言うてはった、点も sleep_random というクラスメソッドの中だけを書き換えて、いろいろ統計を取ってみる・テストしてみればいいわけで。

で、統計を取って評価するプログラムも書いてみようかと思ったけど、もう、夜も遅いので今日はここまで。