Top Page > Ruby 小物集 > 小ネタ編


Ruby 小物集 小ネタ編


実用性はない(と思う)ネタ系ライブラリ。ぼちぼち追加予定。


dispatch

ソース: dispatch.rb

引数型によるメソッドオーバロードができるようにするライブラリ。Rubyの文法を最大限に悪用した、奇怪な構文が特徴。

  def hoge(*args)
    dispatch(args).
      when(Integer) do |i|
        printf("Integer %d\n", i)
      end.
      when(String) do |s|
        printf("String %s\n", s)
      end.
      when(String, Integer) do |s, i|
        printf("String %s and Integer %d\n", s, i)
      end.
    end
  end
  
  hoge(3)
  hoge("s")
  hoge("t", 4)

StrongTypingがもっとまっとうな構文で同じ事を実現してるので、使うならこちらをお勧めします(笑)。


product

ソース: product.rb

クラスの組(product)に対してメソッドを定義できるようにするライブラリ。

例えば以下では、AcidクラスとBaseクラスの組に対して、saltというメソッドを定義しています。

  class Acid
      include(Producable)
      attr_accessor(:anion)
  end
  
  class Base
      include(Producable)
      attr_accessor(:cation)
  end
  
  def_product(Acid*Base) do
      def salt
        return rhs.cation + lhs.anion
      end
  end

使うときはこんな感じ。

  h_cl= Acid.new()
  h_cl.anion= "Cl"
  na_oh= Base.new()
  na_oh.cation= "Na"
  
  p (h_cl*na_oh).salt    # => "NaCl"
  p (h_cl*na_oh).class   # => Acid*Base

一応、元のクラスの継承関係も反映されます。

  class WeakBase < Base
  end
  
  def_product(Acid*WeakBase) do
      def acid?
        return true
      end
  end
  
  nh4_oh= WeakBase.new()
  nh4_oh.cation= "NH4"
  
  p (h_cl*nh4_oh).salt               # => "NH4Cl"
  p (h_cl*nh4_oh).acid?              # => true
  p (h_cl*nh4_oh).is_a?(Acid*Base)   # => true

ただ、この継承には色々制限が有って、例えば、Acid*Baseより前にAcid*WeakBaseを定義してしまうと、変になります。あと、Rubyでは多重継承ができないので、基底クラス候補が複数いるような状況では、それらに共通の基底クラスが、基底クラスになります(わけわからん)。

もちろん、Arrayなどの既存のクラスのproductも定義できます。ただ、*演算子だと衝突するので、もうちょっと穏健な(?)productという関数も用意しました。

  def_product(Array*Array) do
      def map(&block)
        return (0...lhs.size).map(){ |i| yield(lhs[i], rhs[i]) }
      end
  end
  
  p product([1, 2], [3, 4]).map(){ |a, b| a+b }   # => [4, 6]

3個以上のproductは、「productのproduct」として定義できます。

  def_product(Object*Symbol*Array) do
      def call()
        obj= lhs.lhs
        sym= lhs.rhs
        ary= rhs
        obj.send(sym, *ary)
      end
  end
  
  p product("hoge", :gsub, [/o/, "e"]).call()   # => "hege"

O/Rマッパみたいなものを考えてて、複数テーブルに紐づくテーブルってオブジェクトではどう書くんだろうと思って、思いついたもの。


小ネタ編 < Ruby 小物集 < TopPage