トップ «前の日記(2007-05-02) 最新 次の日記(2007-05-04)» 編集

Route 477



2007-05-03

[scheme] SICPはじめました

http://sicp.g.hatena.ne.jp/yhara/

なんとなく勢いでSICP(日本語版)を買ってしまったので、淡々と問題を解いていこうかなと思います。 ユニットテストが書けそうなものはgauche.testを使ってテストファーストで。

[ruby] Ruby/AnarchyGolf

Hpricotを使って、AnarchyGolfのスクレイパを書いてみました。

使用例。

yhara@meteor:~/HTML/anagol % irb -r lib/anagol.rb
>> anagol = AnarchyGolf.new
=> #<AnarchyGolf:0x2aaaac15e9f0 @html={}>
>> langs = anagol.languages
=> [#<struct AnarchyGolf::Language name="Ruby", short_name="rb">, 
    (中略),
    #<struct AnarchyGolf::Language name="x86", short_name="out">]
>> probs = anagol.problems
=> [#<AnarchyGolf::Problem:0x2aaaacf21600 @name="hello world">, 
    (中略),
    #<AnarchyGolf::Problem:0x2aaaacf1dd70 @name="128 bits">]
>> hw = probs.first
=> #<AnarchyGolf::Problem:0x2aaaacf21600 @name="hello world">
>> hw.name
=> "hello world"
>> hw.url
=> "http://golf.shinh.org/p.rb?hello+world"
>> hw.description
=> "say "Hello, world!""
>> hw.deadline
=> nil
>> hw.revealed?
=> false
>> hw.ranking["Ruby"].first
=> #<struct AnarchyGolf::Problem::Score rank=1, lang="Ruby", user="eban", size=19, score=nil, time=0.1226, date="07/01/30 16:37:51", stat="?B / ?B / ?B">
>> hw.language_ranking.first
=> #<struct AnarchyGolf::Problem::Score rank=1, lang="PHP", user="konbu", size=13, score=10000, time=nil, date=nil, stat=nil>
>> hw.has_language?("Befunge")
=> true

problemsを呼んだときに各問題に対応するProblemのインスタンスが生成される……のですが、 problemsを呼ぶだけで全問題のURLにアクセスするとサーバに負荷がかかりすぎるので、 Problem#descriptionやProblem#rankingといったプロパティは「実際にアクセスされたときに初めて値を取りに行く」 ようになっています。

実装はこんな感じ。

module CachedAttribute
  def cached_attr_reader(*syms)
    syms.each do |attr|
      module_eval <<-EOD
        def #{attr}
          if defined? @#{attr}
            @#{attr}
          else
            @#{attr} = update_#{attr}
          end
        end
      EOD
    end
  end
end

class AnarchyGolf
  class Problem
    extend CachedAttribute
    cached_attr_reader :description, :deadline, :revealed
    cached_attr_reader :ranking, :language_ranking
    ...
    def update_ranking
      # 最初にProblem#rankingが呼ばれたときだけ実行される

さて、何がやりたかったかというと、UnlambdaとかErlangとかマイナーな言語の簡単なサンプルコードが欲しかったのでした。 *1 とりあえずanagol tableを作って目的は達成された…のですが、 実際にコードを見たところでgolfされてるから意味不明という罠が。しまった!

*1 最近の問題は一定時間で回答が公開されるようになってたりする

[ruby] twitter gemのソースを読んでみたんだが

%w(uri net/http yaml rubygems hpricot active_support).each { |f| require f }

そんなとこ省略すんなよw

[ruby] twitter gemのソースを読んでみたんだが(2)

rescue のあとに何も書かないのはエラーを見逃す可能性があるのでおすすめできない。

ちゃんと rescue ArgumentError とか、どの例外をキャッチするのか書きましょう。