関数型言語Ruby (3)

場当たり的にパターンマッチを実装しました。とりあえずはこんなところでいいか。もう。
map。

define(:map, [X, []]) do
  []
end
define(:map, [X, X_XS]) do |f, x, xs|
  [f[x]] + map[f, xs]
end

filter。

define(:filter, [X, []]) do
  []
end
define(:filter, [X, X_XS]) do |f, x, xs|
  if f[x]
    [x] + filter[f, xs]
  else
    filter[f, xs]
  end
end

実装。

module FunctionalRuby
  FUNCS = {}

  X = Object.new
  X_XS = Object.new

  class Function
    def initialize(sym)
      @sym = sym
      @func = []
    end

    def add(pat, &f)
      @func.push([pat, f])
    end

    def [](*xs)
      @func.each do |func|
        pat, f = *func
        xs2 = match_pattern?(pat, xs)
        return f[*xs2] if xs2
      end
      raise(ArgumentError, "no match pattern. #{@sym}") unless f
    end

    private

    def match_pattern?(pat, xs)
      return xs unless pat 
      return nil unless pat.size == xs.size
      xs2 = []
      pat.zip(xs) do |pat, x|
        case pat
        when X
          xs2 << x
          next
        when X_XS
          y, *ys = *x
          xs2 << y
          xs2 << ys
          next
        when x
          next
        else
          return nil
        end
      end
      xs2
    end
  end

  def define(sym, pat = nil, &f)
    FUNCS[sym] ||= Function.new(sym)
    FUNCS[sym].add(pat, &f)
    self.class.module_eval("def #{sym}; fun(:#{sym}); end")
  end

  def curry(f, *vs)
    lambda {|v| f[vs + [v]] }
  end

  def fun(sym)
    FUNCS[sym]
  end
end