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

Route 477



2007-02-24

[prog] キューとスタック

ふと気付いたんだが、エスカレーターはFIFOでエレベーターはLIFOですね。

[event] LiveCoding第3回に行ってきた

面白かった!スタッフの方、出演者の方どうもありがとうございました。

感想:

  • スイッチ楽しい
  • ピザを頼むのは案外難しい

[ruby] Webサービス経由で足し算を行うライブラリ:jitor-int.rb

LiveCoding中に氏久さんが作ったIntというサービスを利用するライブラリを作ってみました。

Intは整数の演算を行うWebサービスで、例えば http://int.jitor.net/add/3/4 にアクセスすると"7"と書かれたページが 得られます。

さて、これをRubyから使うにはどういうAPIが良いでしょうか?JitorInt.add(3,4) とか? いやいや、こんな長いのは覚えにくいし、足し算を行うのにこんなのをいちいち書いてられませんよね。 「良くつかうものは短い名前にする」という原則に従えば、ここは組込みのFixnum#+をオーバーライドするしか ありません。

というわけで、jitor-int.rbです。

require 'open-uri'

class Fixnum
  def use_orig
    alias :+ :add_orig
    result = yield
    alias :+ :add_jitor
    result
  end

  def add_jitor(other)
    url = "http://int.jitor.net/add/#{self}/#{other}"
    puts "accessing to #{url}..."

    result = use_orig{ open(url).read }

    p result
    result.to_i
  end

  alias :add_orig :+
  alias :+ :add_jitor
end

これを使うと、例えば

require 'jitor-int'

p 1 + 2 + 3

のようなスクリプトが

accessing to http://int.jitor.net/add/1/2...
"3"
accessing to http://int.jitor.net/add/3/3...
"6"
6

のような感じで動きます。require 'jitor-int' と書くだけで、Webサービス経由で足し算できるようになります。簡単ですね :-)

このライブラリがあれば、突然Rubyで足し算ができなくなっても安心!…と言いたいところなのですが、 実はopen-uriが中で Fixnum#+ を使っているため組込みの「+」は残念ながら必要です。

また普通にオーバーライド しただけでは無限再帰になってしまうので、Webにアクセスするところだけ + の定義を組込みのものに戻しています。

おまけ

「-」「*」「%」にも対応したバージョンを以下に貼っておきます。(「/」がないのは仕様です。)

require 'open-uri'

class Fixnum
  SYMS = {
    :+ => :add,
    :- => :sub,
    :* => :multi,
    :% => :mod
  }
  def switch_method(sym, method)
    self.class.instance_eval do
      alias_method sym, method
    end
  end

  def use_orig
    SYMS.each{|sym, name| switch_method(sym, "#{sym}_orig")}
    result = yield
    SYMS.each{|sym, name| switch_method(sym, name)}
    result
  end

  def jitor(type,a,b)
    url = "http://int.jitor.net/#{type}/#{a}/#{b}"
    puts "accessing to #{url}..."

    result = use_orig{ open(url).read }

    p result
    result.to_i
  end

  SYMS.each do |sym, name|
    define_method name do |other|
      jitor(name, self, other)
    end
    alias_method "#{sym}_orig", sym
    alias_method sym, name
  end

end