car, cdr, cons

car や cdr を初めて知った Rubyist が初めてやるだろうことをやっとくよ。

#!/usr/bin/ruby

class Array
   def method_missing(name, *args)
      if name.to_s =~ /^c([ad]+)r$/
         $1.split(//).reverse.inject(self) do |cons, ch|
            (ch == "a") ? cons[0] : (cons.size > 2) ? cons[1..-1] : cons[1]
         end
      else
         raise NoMethodError.new(name, args)
         # i should raise a "NameError" exception?
      end
   end

   def respond_to?(name, priv=false)
      (name.to_s =~ /^c([ad]+)r$/) ? true : super(name, priv)
   end
end

if __FILE__ == $0
   x = [0, true]
   p x.car
   p x.cdr

   y = [[1, 2], 3]
   p y.caar
   p y.cdar

   z = [[[[[[1, 2], 3], 4], 5], 6], 7]
   p z.caaaaaar
   p z.caaaaar
   p z.caaaar
end

結果:

$ ruby cons.rb
0
true
1
2
1
[1, 2]
[[1, 2], 3]


初めて inject が決まったような気がする。


気がかり:

  • method_missing 使ったときは respond_to? も再定義しろって言うけどどういうこと?
    • 実装した。
  • 例外は何を上げるべきか?