From: MikkelFJ Date: 2002-10-21T09:52:23+09:00 Subject: Duck patterns in Ruby I was just thinking about a problem, and I happened to be pseudo coding partially in Ruby, partially something else. Then I figured the pseudo code might be useful Ruby. In Ruby you can use case / when to branch you code based on object type. But it's generally not seen as good style to branch on type in Ruby, because it violates the duck typing principle. (If it quacks its a duck). But in line with Ruby's duck typing why not add some duck matching: My original problem involved getting arguments in that was either a collection or a single item, for example a generic product method. So I thought it would be nice to be able to branch the code based on whether an argument had the "each" method. This lead to the idea of a kind of pattern matching based on available methods instead of the more strict matching on a class. def product (x, y) p = 0 match_methods(x, y) when(:each, nil) x.each {|a| p = p + a.multiply(y) } when(nil, :each) y.each {|b| p = p + x.multiply(b) } when(nil, nil) p = x.multiply(y) end return p end (Might also be nice to branch based on whether a method yields or takes a code block as argument). It is somewhat similar to type matching in languages like OCaml, except here you match the duck type, not the class type. In the above example, more than one argument could be involved. In the following example a single argument is used, but more methods can be avaialbe. As with case statements the first match top down is executed. def classify creature match_methods (creature) when(:quacks :wings) puts "duck" when(:quacks) puts ("hunter") when(:wings :feather) puts "bird" when(:wings :nocturnal) puts "probably bat or batman" when(:wings) puts "airborne" when(:legs) if creature.legs.count == 8 then puts "spider" else puts "walking creature" end end Mikkel