Functor

元ネタ: http://dev.zeraweb.com/introducing-functor/

class Functor {
  Functor(Closure c){ with c }
  def rules = []
  def proc = { ...a -> exec a }
  def given(Object[] args){
    def pat = args as List
    rules << [pat, pat.pop()]
  }
  def exec(...args){ match(args as List).call(args) }
  def match(List args){
    def rule = rules.find{ doesMatch(args, it[0]) }
    if(!rule) throw new Exception(
      'Argument error: no functor matches the given arguments.')
    rule[1]
  }
  private def doesMatch(args, pats){
    def s = args.size()
    s == pats.size() && (0..<s).every{ pats[it].isCase args[it]  }
  }
}

fib = new Functor(){
  given(0){ 0 }
  given(1){ 1 }
  given(Integer){ exec( it - 1 ) + exec( it - 2 ) }
}
10.times{ println fib.exec(it) }

fzbz = new Functor(){
  given({ it % 15 == 0 }){ println 'FizzBuzz' }
  given({ it %  5 == 0 }){ println 'Buzz' }
  given({ it %  3 == 0 }){ println 'Fizz' }
  given(Number){ println it }
}
(1..100).each fzbz.proc

カッコよさげに見えたので真似してみたが,大して嬉しく無いような気も。

fib = { switch(it){
  case 0: return 0
  case 1: return 1
  case Integer: return call(it - 1) + call(it - 2)
}}
10.times{ println fib.exec(it) }

fzbz = { switch(it){
  case { it % 15 == 0 }: println 'FizzBuzz'; break
  case { it %  5 == 0 }: println 'FizzBuzz'; break
  case { it %  3 == 0 }: println 'FizzBuzz'; break
  default: println it;
}}
(1..100).each fzbz

これでいいやん,という。