<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Object Mentor Blog: Tighter Ruby Methods with Functional-style Pattern Matching, Using the Case Gem</title>
    <link>http://blog.objectmentor.com/articles/2009/03/16/tighter-ruby-methods-with-functional-style-pattern-matching-using-the-case-gem</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description></description>
    <item>
      <title>Tighter Ruby Methods with Functional-style Pattern Matching, Using the Case Gem</title>
      <description>&lt;p&gt;Ruby doesn&amp;#8217;t have overloaded methods, which are methods with the same name, but different &lt;em&gt;signatures&lt;/em&gt; when you consider the argument lists and return values. This would be somewhat challenging to support in a dynamic language with very flexible options for method argument handling.&lt;/p&gt;


	&lt;p&gt;You can &amp;#8220;simulate&amp;#8221; overloading by parsing the argument list and taking different paths of execution based on the structure you find. This post discusses how &lt;em&gt;pattern matching&lt;/em&gt;, a hallmark of &lt;em&gt;functional programming&lt;/em&gt;, gives you powerful options.&lt;/p&gt;


	&lt;p&gt;First, let&amp;#8217;s look at a typical example that handles the arguments in an &lt;em&gt;ad hoc&lt;/em&gt; fashion. Consider the following &lt;code&gt;Person&lt;/code&gt; class. You can pass three arguments to the initializer, the &lt;code&gt;first_name&lt;/code&gt;, the &lt;code&gt;last_name&lt;/code&gt;, and the &lt;code&gt;age&lt;/code&gt;. Or, you can pass a hash using the keys &lt;code&gt;:first_name&lt;/code&gt;, &lt;code&gt;:last_name&lt;/code&gt;, and &lt;code&gt;:age&lt;/code&gt;.&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
require "rubygems" 
require "spec" 

class Person
  attr_reader :first_name, :last_name, :age
  def initialize *args
    arg = args[0]
    if arg.kind_of? Hash       # 1
      @first_name = arg[:first_name]
      @last_name  = arg[:last_name]
      @age        = arg[:age]
    else
      @first_name = args[0]
      @last_name  = args[1]
      @age        = args[2]
    end
  end
end

describe "Person#initialize" do 
  it "should accept a hash with key-value pairs for the attributes" do
    person = Person.new :first_name =&amp;gt; "Dean", :last_name =&amp;gt; "Wampler", :age =&amp;gt; 39
    person.first_name.should == "Dean" 
    person.last_name.should  == "Wampler" 
    person.age.should        == 39
  end
  it "should accept a first name, last name, and age arguments" do
    person = Person.new "Dean", "Wampler", 39
    person.first_name.should == "Dean" 
    person.last_name.should  == "Wampler" 
    person.age.should        == 39
  end
end
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;The condition on the &lt;code&gt;# 1&lt;/code&gt; comment line checks to see if the first argument is a &lt;code&gt;Hash&lt;/code&gt;. If so, the attribute&amp;#8217;s values are extracted from it. Otherwise, it is assumed that three arguments were specified in a particular order. They are passed to &lt;code&gt;#initialize&lt;/code&gt; in a three-element array. The two &lt;a href="http://rspec.info"&gt;rspec&lt;/a&gt; &lt;em&gt;examples&lt;/em&gt; exercise these behaviors. For simplicity, we ignore some more general cases, as well as error handling.&lt;/p&gt;


	&lt;p&gt;Another approach that is more flexible is to use duck typing, instead. For example, we could replace the line with the &lt;code&gt;# 1&lt;/code&gt; comment with this line:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
if arg.respond_to? :has_key?
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;There aren&amp;#8217;t many objects that respond to &lt;code&gt;#has_key?&lt;/code&gt;, so we&amp;#8217;re highly confident that we can use &lt;code&gt;[symbol]&lt;/code&gt; to extract the values from the hash.&lt;/p&gt;


	&lt;p&gt;This implementation is fairly straightforward. You&amp;#8217;ve probably written code like this yourself. However, it could get complicated for more involved cases.&lt;/p&gt;


	&lt;h2&gt;Pattern Matching, a Functional Programming Approach&lt;/h2&gt;


	&lt;p&gt;Most programming languages today have &lt;code&gt;switch&lt;/code&gt; or &lt;code&gt;case&lt;/code&gt; statements of some sort and most have support for regular expression matching. However, in &lt;em&gt;functional programming&lt;/em&gt; languages, pattern matching is so important and pervasive that these languages offer very powerful and convenient support for pattern matching.&lt;/p&gt;


	&lt;p&gt;Fortunately, we can get powerful pattern matching, typical of functional languages, in Ruby using the &lt;a href="http://rubyforge.org/frs/?group_id=3690"&gt;Case&lt;/a&gt; gem that is part of the MenTaLguY&amp;#8217;s &lt;a href="http://rubyforge.org/frs/?group_id=3690"&gt;Omnibus Concurrency library&lt;/a&gt;. &lt;code&gt;Omnibus&lt;/code&gt; provides support for the hot &lt;em&gt;Actor model of concurrency&lt;/em&gt;, which Erlang has made famous. However, it would be a shame to restrict the use of the &lt;code&gt;Case&lt;/code&gt; gem to parsing Actor messages. It&amp;#8217;s much more general purpose than that.&lt;/p&gt;


	&lt;p&gt;Let&amp;#8217;s rework our example using the &lt;a href="http://rubyforge.org/frs/?group_id=3690"&gt;Case&lt;/a&gt; gem.&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
require "rubygems" 
require "spec" 
require "case" 

class Person
  attr_reader :first_name, :last_name, :age
  def initialize *args
    case args
    when Case[Hash]       # 1
      arg = args[0]
      @first_name = arg[:first_name]
      @last_name  = arg[:last_name]
      @age        = arg[:age]
    else
      @first_name = args[0]
      @last_name  = args[1]
      @age        = args[2]
    end
  end
end

describe "Person#initialize" do 
  it "should accept a first name, last name, and age arguments" do
    person = Person.new "Dean", "Wampler", 39
    person.first_name.should == "Dean" 
    person.last_name.should  == "Wampler" 
    person.age.should        == 39
  end
  it "should accept a has with :first_name =&amp;gt; fn, :last_name =&amp;gt; ln, and :age =&amp;gt; age" do
    person = Person.new :first_name =&amp;gt; "Dean", :last_name =&amp;gt; "Wampler", :age =&amp;gt; 39
    person.first_name.should == "Dean" 
    person.last_name.should  == "Wampler" 
    person.age.should        == 39
  end
end
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;We require the &lt;code&gt;case&lt;/code&gt; gem, which puts the &lt;code&gt;#===&lt;/code&gt; method on steroids. In the &lt;code&gt;when&lt;/code&gt; statement in &lt;code&gt;#initialize&lt;/code&gt;, the expression &lt;code&gt;when Case[Hash]&lt;/code&gt; matches on a one-element array where the element is a &lt;code&gt;Hash&lt;/code&gt;. We extract the key-value pairs as before. The &lt;code&gt;else&lt;/code&gt; clause assumes we have an array for the arguments.&lt;/p&gt;


	&lt;p&gt;So far, this is isn&amp;#8217;t very impressive, but all we did was to reproduce the original behavior. Let&amp;#8217;s extend the example to really exploit some of the neat features of the &lt;code&gt;Case&lt;/code&gt; gem&amp;#8217;s pattern matching. First, let&amp;#8217;s narrow the allowed array values.&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
require "rubygems" 
require "spec" 
require "case" 

class Person
  attr_reader :first_name, :last_name, :age
  def initialize *args
    case args
    when Case[Hash]       # 1
      arg = args[0]
      @first_name = arg[:first_name]
      @last_name  = arg[:last_name]
      @age        = arg[:age]
    when Case[String, String, Integer]
      @first_name = args[0]
      @last_name  = args[1]
      @age        = args[2]
    else
      raise "Invalid arguments: #{args}" 
    end
  end
end

describe "Person#initialize" do 
  it "should accept a first name, last name, and age arguments" do
    person = Person.new "Dean", "Wampler", 39
    person.first_name.should == "Dean" 
    person.last_name.should  == "Wampler" 
    person.age.should        == 39
  end
  it "should accept a has with :first_name =&amp;gt; fn, :last_name =&amp;gt; ln, and :age =&amp;gt; age" do
    person = Person.new :first_name =&amp;gt; "Dean", :last_name =&amp;gt; "Wampler", :age =&amp;gt; 39
    person.first_name.should == "Dean" 
    person.last_name.should  == "Wampler" 
    person.age.should        == 39
  end
  it "should not accept an array unless it is a [String, String, Integer]" do
    lambda { person = Person.new "Dean", "Wampler", "39" }.should raise_error(Exception)
  end
end
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;The new expression &lt;code&gt;when Case[String, String, Integer]&lt;/code&gt; only matches a three-element array where the first two arguments are strings and the third argument is an integer, which are the types we want. If you use an array with a different number of arguments or the arguments have different types, this &lt;code&gt;when&lt;/code&gt; clause won&amp;#8217;t match. Instead, you&amp;#8217;ll get the default &lt;code&gt;else&lt;/code&gt; clause, which raises an exception. We added another rspec example to test this condition, where the user&amp;#8217;s age was specified as a string instead of as an integer. Of course, you could decide to attempt a conversion of this argument, to make your code more &amp;#8220;forgiving&amp;#8221; of user mistakes.&lt;/p&gt;


	&lt;p&gt;Similarly, what happens if the method supports default values some of the parameters. As written, we can&amp;#8217;t support that option, but let&amp;#8217;s look at a slight variation of &lt;code&gt;Person#initialize&lt;/code&gt;, where a hash of values is not supported, to see what would happen.&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
require "rubygems" 
require "spec" 
require "case" 

class Person
  attr_reader :first_name, :last_name, :age
  def initialize first_name = "Bob", last_name = "Martin", age = 29
    case [first_name, last_name, age]
    when Case[String, String, Integer]
      @first_name = first_name
      @last_name  = last_name
      @age        = age
    else
      raise "Invalid arguments: #{first_name}, #{last_name}, #{age}" 
    end
  end
end

def check person, expected_fn, expected_ln, expected_age
  person.first_name.should == expected_fn
  person.last_name.should  == expected_ln
  person.age.should        == expected_age
end

describe "Person#initialize" do 
  it "should require a first name (string), last name (string), and age (integer) arguments" do
    person = Person.new "Dean", "Wampler", 39
    check person, "Dean", "Wampler", 39
  end
  it "should accept the defaults for all parameters" do
    person = Person.new
    check person, "Bob", "Martin", 29
  end
  it "should accept the defaults for the last name and age parameters" do
    person = Person.new "Dean" 
    check person, "Dean", "Martin", 29
  end
  it "should accept the defaults for the age parameter" do
    person = Person.new "Dean", "Wampler" 
    check person, "Dean", "Wampler", 29
  end
  it "should not accept the first name as a symbol" do
    lambda { person = Person.new :Dean, "Wampler", "39" }.should raise_error(Exception)
  end
  it "should not accept the last name as a symbol" do
  end
  it "should not accept the age as a string" do
    lambda { person = Person.new "Dean", "Wampler", "39" }.should raise_error(Exception)
  end
end
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;We match on all three arguments as an array, asserting they are of the correct type. As you might expect, &lt;code&gt;#initialize&lt;/code&gt; always gets three parameters passed to it, including when default values are used.&lt;/p&gt;


	&lt;p&gt;Let&amp;#8217;s return to our original example, where the object can be constructed with a hash or a list of arguments. There are two more things (at least &amp;#8230;) that we can do. First, we&amp;#8217;re not yet validating the types of the values in the hash. Second, we can use the &lt;code&gt;Case&lt;/code&gt; gem to impose constraints on the values, such as requiring non-empty name strings and a positive age.&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
require "rubygems" 
require "spec" 
require "case" 

class Person
  attr_reader :first_name, :last_name, :age
  def initialize *args
    case args
    when Case[Hash]
      arg = args[0]
      @first_name = arg[:first_name]
      @last_name  = arg[:last_name]
      @age        = arg[:age]
    when Case[String, String, Integer]
      @first_name = args[0]
      @last_name  = args[1]
      @age        = args[2]
    else
      raise "Invalid arguments: #{args}" 
    end
    validate_name @first_name, "first_name" 
    validate_name @last_name, "last_name" 
    validate_age
  end

  protected

  def validate_name name, field_name
    case name
    when Case::All[String, Case.guard {|s| s.length &amp;gt; 0 }]
    else
      raise "Invalid #{field_name}: #{first_name}" 
    end
  end

  def validate_age
    case @age
    when Case::All[Integer, Case.guard {|n| n &amp;gt; 0 }]
    else
      raise "Invalid age: #{@age}" 
    end
  end
end

describe "Person#initialize" do 
  it "should accept a first name, last name, and age arguments" do
    person = Person.new "Dean", "Wampler", 39
    person.first_name.should == "Dean" 
    person.last_name.should  == "Wampler" 
    person.age.should        == 39
  end
  it "should accept a has with :first_name =&amp;gt; fn, :last_name =&amp;gt; ln, and :age =&amp;gt; age" do
    person = Person.new :first_name =&amp;gt; "Dean", :last_name =&amp;gt; "Wampler", :age =&amp;gt; 39
    person.first_name.should == "Dean" 
    person.last_name.should  == "Wampler" 
    person.age.should        == 39
  end
  it "should not accept an array unless it is a [String, String, Integer]" do
    lambda { person = Person.new "Dean", "Wampler", "39" }.should raise_error(Exception)
  end
  it "should not accept a first name that is a zero-length string" do
    lambda { person = Person.new "", "Wampler", 39 }.should raise_error(Exception)
  end    
  it "should not accept a first name that is not a string" do
    lambda { person = Person.new :Dean, "Wampler", 39 }.should raise_error(Exception)
  end    
  it "should not accept a last name that is a zero-length string" do
    lambda { person = Person.new "Dean", "", 39 }.should raise_error(Exception)
  end    
  it "should not accept a last name that is not a string" do
    lambda { person = Person.new :Dean, :Wampler, 39 }.should raise_error(Exception)
  end    
  it "should not accept an age that is less than or equal to zero" do
    lambda { person = Person.new "Dean", "Wampler", -1 }.should raise_error(Exception)
    lambda { person = Person.new "Dean", "Wampler", 0 }.should raise_error(Exception)
  end    
  it "should not accept an age that is not an integer" do
    lambda { person = Person.new :Dean, :Wampler, "39" }.should raise_error(Exception)
  end    
end
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;We have added &lt;code&gt;validate_name&lt;/code&gt; and &lt;code&gt;validate_age&lt;/code&gt; methods that are invoked at the end of &lt;code&gt;#initialize&lt;/code&gt;. In &lt;code&gt;validate_name&lt;/code&gt;, the one &lt;code&gt;when&lt;/code&gt; clause requires &amp;#8220;all&amp;#8221; the conditions to be true, that the name is a string and that it has a non-zero length. Similarly, &lt;code&gt;validate_age&lt;/code&gt; has a &lt;code&gt;when&lt;/code&gt; clause that requires &lt;code&gt;age&lt;/code&gt; to be a positive integer.&lt;/p&gt;


	&lt;h2&gt;Final Thoughts&lt;/h2&gt;


	&lt;p&gt;So, how valuable is this? The code is certainly longer, but it specifies and enforces expected behavior more precisely. The rspec examples verify the enforcement. It smells a little of static typing, which is good or bad, depending on your point of view. ;)&lt;/p&gt;


	&lt;p&gt;Personally, I think the conditional checks are a good way to add robustness in small ways to libraries that will grow and evolve for a long time. The checks document the required behavior for code readers, like new team members, but of course, they should really get that information from the tests. ;) (However, it would be nice to extract the information into the &lt;code&gt;rdocs&lt;/code&gt;.)&lt;/p&gt;


	&lt;p&gt;For small, short-lived projects, I might not worry about the conditional checks as much (but how many times have those &amp;#8220;short-lived projects&amp;#8221; refused to die?).&lt;/p&gt;


	&lt;p&gt;You can read more about &lt;code&gt;Omnibus&lt;/code&gt; and &lt;code&gt;Case&lt;/code&gt; in this &lt;a href="http://www.infoq.com/articles/actors-rubinius-interview"&gt;InfoQ interview&lt;/a&gt; with MenTaLguY. I didn&amp;#8217;t discuss using the Actor model of concurrency, for which these gems were designed. For an example of Actors using Omnibus, see my &lt;a href="http://aspectprogramming.com/papers/BetterRubyThroughFP_v5.pdf"&gt;Better Ruby through Functional Programming&lt;/a&gt; presentation or the &lt;a href="http://confreaks.com/"&gt;Confreak&amp;#8217;s&lt;/a&gt; video of an earlier version of the presentation I gave at last year&amp;#8217;s &lt;a href="http://rubyconf2008.confreaks.com/better-ruby-through-functional-programming-2.html"&gt;RubyConf&lt;/a&gt;.&lt;/p&gt;</description>
      <pubDate>Mon, 16 Mar 2009 19:59:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:4e6b0c8e-7b8b-4c8d-b20c-6e30fe39c98c</guid>
      <author>Dean Wampler</author>
      <link>http://blog.objectmentor.com/articles/2009/03/16/tighter-ruby-methods-with-functional-style-pattern-matching-using-the-case-gem</link>
      <category>Dean's Deprecations</category>
      <category>Dynamic Languages</category>
      <category>Design Principles</category>
      <category>Ruby</category>
      <category>methods</category>
      <category>functional</category>
      <category>programming</category>
      <category>pattern</category>
      <category>matching</category>
    </item>
    <item>
      <title>"Tighter Ruby Methods with Functional-style Pattern Matching, Using the Case Gem" by toms shoes</title>
      <description>&lt;p&gt;You will find that &lt;a href="http://www.cheaptomsshoessaleusa.com/" rel="nofollow"&gt;toms shoes&lt;/a&gt; are comfortable to wear While you can get &lt;a href="http://www.cheaptomsshoessaleusa.com/" rel="nofollow"&gt;cheap toms&lt;/a&gt; at low price online. Maybe &lt;a href="http://www.cheaptomsshoessaleusa.com/last-chance-c-3.html" rel="nofollow"&gt;toms last chance shoes&lt;/a&gt; will be your favorite.&lt;/p&gt;</description>
      <pubDate>Wed, 08 Feb 2012 21:33:52 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:9b168c66-2b26-45bb-9240-32353113a5e4</guid>
      <link>http://blog.objectmentor.com/articles/2009/03/16/tighter-ruby-methods-with-functional-style-pattern-matching-using-the-case-gem#comment-202518</link>
    </item>
    <item>
      <title>"Tighter Ruby Methods with Functional-style Pattern Matching, Using the Case Gem" by http://www.jerseyscheapusa.com</title>
      <description>&lt;p&gt;cheapjerseysusa ,site &lt;a href="http://www.jerseyscheapusa.com" rel="nofollow"&gt;http://www.jerseyscheapusa.com&lt;/a&gt; , offer cheap nfl jerseys and cheapjerseysusa .our mission is to gain a cheap jerseys sustainable competitive advantage by providing cheap jerseys customers the highest quality jerseys and cheapjerseysusa services. offering all the authentic cheap jerseys , cheap nfl jerseys ,nhl cheap nfl jerseys ,nba jerseys,mlb cheapjerseysusa ,&amp;#8221; cheap jerseys Quantity first and customer foremost&amp;#8221;is our jerseys top priority. We really hope to expand our cheapjerseysusa business and cheap nfl jerseys through cooperation with cheap jerseys individuals and companies from all over the world.&lt;/p&gt;</description>
      <pubDate>Sat, 28 Jan 2012 20:44:31 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:80689ae1-2eb8-44cd-a0ac-7b2ff38bed56</guid>
      <link>http://blog.objectmentor.com/articles/2009/03/16/tighter-ruby-methods-with-functional-style-pattern-matching-using-the-case-gem#comment-199849</link>
    </item>
    <item>
      <title>"Tighter Ruby Methods with Functional-style Pattern Matching, Using the Case Gem" by dealers license</title>
      <description>&lt;p&gt;very nice blog i like it and wanna say thank you for sharing it  here so keep it up man for your fellows&lt;/p&gt;</description>
      <pubDate>Mon, 23 Jan 2012 04:41:41 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:ec33243e-7cf9-4643-812c-0e295ab8aa73</guid>
      <link>http://blog.objectmentor.com/articles/2009/03/16/tighter-ruby-methods-with-functional-style-pattern-matching-using-the-case-gem#comment-198863</link>
    </item>
    <item>
      <title>"Tighter Ruby Methods with Functional-style Pattern Matching, Using the Case Gem" by calcular peso ideal</title>
      <description>&lt;p&gt;What a nice piece of ruby code. Love Ruby and Dynamic languages&lt;/p&gt;</description>
      <pubDate>Sun, 18 Dec 2011 08:30:07 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:2863d557-3a22-4e13-87fd-144bad89c8e4</guid>
      <link>http://blog.objectmentor.com/articles/2009/03/16/tighter-ruby-methods-with-functional-style-pattern-matching-using-the-case-gem#comment-188808</link>
    </item>
    <item>
      <title>"Tighter Ruby Methods with Functional-style Pattern Matching, Using the Case Gem" by tv guide</title>
      <description>&lt;p&gt;thanks alot. great stuff&lt;/p&gt;</description>
      <pubDate>Wed, 07 Dec 2011 14:06:43 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:29eaf91a-fd4d-4573-b865-fe5b68a3189f</guid>
      <link>http://blog.objectmentor.com/articles/2009/03/16/tighter-ruby-methods-with-functional-style-pattern-matching-using-the-case-gem#comment-184255</link>
    </item>
    <item>
      <title>"Tighter Ruby Methods with Functional-style Pattern Matching, Using the Case Gem" by Sac Gucci</title>
      <description>&lt;p&gt;Conception unique de la &lt;a href="http://www.sacgucci-pascher.com" rel="nofollow"&gt;Sac Gucci&lt;/a&gt; est tr&#232;s sympa,&lt;a href="http://www.sacgucci-pascher.com" rel="nofollow"&gt;Sac Gucci Soldes&lt;/a&gt; sont de qualit&#233; fiable et &#224; prix raisonnable.&lt;a href="http://www.sacgucci-pascher.com" rel="nofollow"&gt;Sac Gucci Pas Cher&lt;/a&gt; a &#233;t&#233; consid&#233;r&#233; comme un &lt;a href="http://www.sacgucci-pascher.com" rel="nofollow"&gt;Gucci Soldes&lt;/a&gt; signe de tendances de la mode et des &lt;a href="http://www.sacgucci-pascher.com/2009-sacs-%C3%A0-main-gucci-c-1.html" rel="nofollow"&gt;Gucci Sac a main&lt;/a&gt; s&#233;lection symbole de statut social,&lt;a href="http://www.sacgucci-pascher.com/b%C3%A9b%C3%A9s-gucci-c-4.html" rel="nofollow"&gt;Gucci Soldes online&lt;/a&gt; s&#233;lectionnez en ligne un &lt;a href="http://www.sacgucci-pascher.com" rel="nofollow"&gt;Gucci Pas Cher&lt;/a&gt;, facile d&amp;#8217;avoir un &lt;a href="http://www.sacgucci-pascher.com/sacs-de-soir%C3%A9e-gucci-c-17.html" rel="nofollow"&gt;Sac a Main Gucci Soldes 2011&lt;/a&gt; populaire.Oui,d&#233;sormais tomber en amour avec &lt;a href="http://www.sacgucci-pascher.com/sac-gucci-guccissima-c-12.html" rel="nofollow"&gt;Sac Gucci Guccissima&lt;/a&gt;.&lt;/p&gt;</description>
      <pubDate>Thu, 24 Nov 2011 20:23:48 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:a635df90-3e99-41df-9cce-486fbc349088</guid>
      <link>http://blog.objectmentor.com/articles/2009/03/16/tighter-ruby-methods-with-functional-style-pattern-matching-using-the-case-gem#comment-177679</link>
    </item>
    <item>
      <title>"Tighter Ruby Methods with Functional-style Pattern Matching, Using the Case Gem" by beats by dr dre</title>
      <description>&lt;p&gt;A university student&lt;a href="http://www.drdrebeatsheadphones-australia.com" rel="nofollow"&gt;beats by dr dre&lt;/a&gt; caught by the enemy, the enemy tied him at the poles,&lt;a href="http://www.drdrebeatsheadphones-australia.com/justbeats-solo-purple-onear-headphones-with-controltalk-p-234.html" rel="nofollow"&gt;just beats solo headphones purple&lt;/a&gt; and then asked him: say, where are you? You do not say it electrocuted! S&lt;a href="http://www.drdrebeatsheadphones-australia.com/cheap-drdre-beats-studio-limited-edition-headphones-blackyellow-p-185.html" rel="nofollow"&gt;cheap dr.dre beats studio headphones balck/yellow&lt;/a&gt;tudents back to the enemy a word, the result was electrocuted, he said: I am TVU.&lt;a href="http://www.drdrebeatsheadphones-australia.com/cheap-beats-by-drdre-pro-performance-professional-headphones-white-p-192.html" rel="nofollow"&gt;Hot sale beats by dr dre pro  headphones&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Tue, 15 Nov 2011 18:46:32 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:e6b26992-82a6-4632-924d-05a1a4e07c9c</guid>
      <link>http://blog.objectmentor.com/articles/2009/03/16/tighter-ruby-methods-with-functional-style-pattern-matching-using-the-case-gem#comment-173428</link>
    </item>
    <item>
      <title>"Tighter Ruby Methods with Functional-style Pattern Matching, Using the Case Gem" by beats by dr dre</title>
      <description>&lt;p&gt;A university student&lt;a href="http://www.drdrebeatsheadphones-australia.com" rel="nofollow"&gt;beats by dr dre&lt;/a&gt; caught by the enemy, the enemy tied him at the poles,&lt;a href="http://www.drdrebeatsheadphones-australia.com/justbeats-solo-purple-onear-headphones-with-controltalk-p-234.html" rel="nofollow"&gt;just beats solo headphones purple&lt;/a&gt; and then asked him: say, where are you? You do not say it electrocuted! S&lt;a href="http://www.drdrebeatsheadphones-australia.com/cheap-drdre-beats-studio-limited-edition-headphones-blackyellow-p-185.html" rel="nofollow"&gt;cheap dr.dre beats studio headphones balck/yellow&lt;/a&gt;tudents back to the enemy a word, the result was electrocuted, he said: I am TVU.&lt;a href="http://www.drdrebeatsheadphones-australia.com/cheap-beats-by-drdre-pro-performance-professional-headphones-white-p-192.html" rel="nofollow"&gt;Hot sale beats by dr dre pro  headphones&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Tue, 15 Nov 2011 03:54:23 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:2e3dc8fd-4c80-47fd-98c4-455dd1667338</guid>
      <link>http://blog.objectmentor.com/articles/2009/03/16/tighter-ruby-methods-with-functional-style-pattern-matching-using-the-case-gem#comment-173190</link>
    </item>
    <item>
      <title>"Tighter Ruby Methods with Functional-style Pattern Matching, Using the Case Gem" by christian louboutin</title>
      <description>&lt;p&gt;Very interseting , i make the remark of this blog , i will come back again . your blog is very interesting&lt;/p&gt;</description>
      <pubDate>Thu, 03 Nov 2011 11:42:50 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:56aa9942-e04f-4598-a963-5a71c9f154e8</guid>
      <link>http://blog.objectmentor.com/articles/2009/03/16/tighter-ruby-methods-with-functional-style-pattern-matching-using-the-case-gem#comment-167734</link>
    </item>
    <item>
      <title>"Tighter Ruby Methods with Functional-style Pattern Matching, Using the Case Gem" by http://www.uggssale2011.com</title>
      <description>&lt;p&gt;&lt;a href="http://www.uggssale2011.com/" rel="nofollow"&gt; UGG Stiefel g&#252;nstig &lt;/a&gt;, dazu neigen schon mal jemand understandthat Regenw&#228;lder innerhalb der Rate in 6 entbl&#246;&#223;t werden , 000 Hektar pro Stunde Es sollte in der Tat eine &#252;berraschende Nachricht, dass unsere unerfahrenen L&#228;nder auf diese Art von schnellen Ebene abgeschafft werden eher sein, und f&#252;hren die Menschen herauszufinden, was die sch&#228;dlichen Auswirkungen ist in der Regel Nun, die Antwort oft Mischung auf yes plus no.Others k&#246;nnen, sind &#252;berzeugt, dass die Pr&#228;misse, auf eine sterbende Welt gut gesagt, w&#228;hrend andere Leute den Vorteil, dass solche Elemente k&#246;nnte wirklich arise.However leugnen, in Fragen etwas wie dieses, haben die Menschen hat zu glauben, nur von einem Ding gewonnen, und das ist genau das: Regenwald Abholzung w&#252;rde es &#252;ber eine etwas h&#246;here Geschwindigkeit und auch seine besondere sch&#228;dliche Vorteile sind fast unstoppable.We Diskussion der Entwaldung jeden Tag noch wir nie bemerken es die schnelle Ankunft Tempo. Vielleicht ist es als Folge des Mannes fahrl&#228;ssig, dass andere bestehen zu zerst&#246;ren, ohne zu sehen Ihr Potential Ergebnisse ihrer dient k&#246;nnte carry.Man kann nur wahrscheinlich bereuen, wenn die Dinge zu sein, die sie betreffen auf diese Weise dazu neigen, dass sie alle zu einem fabelhaften St&#246;rung so etwas wie ein guter Alltags living.By Beobachten und Sehen und H&#246;ren die wahrscheinlichen Ergebnisse in Entwaldung, muss eine haben Seiten im Inneren der Auswahl unter den guten und b&#246;sen.&lt;/p&gt;</description>
      <pubDate>Tue, 01 Nov 2011 03:38:34 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:9ab90e58-9baa-40ce-8968-b53c1f6f6aeb</guid>
      <link>http://blog.objectmentor.com/articles/2009/03/16/tighter-ruby-methods-with-functional-style-pattern-matching-using-the-case-gem#comment-166658</link>
    </item>
    <item>
      <title>"Tighter Ruby Methods with Functional-style Pattern Matching, Using the Case Gem" by canada goose jakke</title>
      <description>&lt;p&gt;Very interseting , i make the remark of this blog , i will come back again . your blog is very interesting&lt;/p&gt;</description>
      <pubDate>Mon, 31 Oct 2011 10:33:35 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:b157331c-7cb2-49f0-aaa5-5e1429566f28</guid>
      <link>http://blog.objectmentor.com/articles/2009/03/16/tighter-ruby-methods-with-functional-style-pattern-matching-using-the-case-gem#comment-166284</link>
    </item>
    <item>
      <title>"Tighter Ruby Methods with Functional-style Pattern Matching, Using the Case Gem" by Nike run free</title>
      <description>&lt;p&gt;Pretty good post. I just stumbled upon your blog and wanted to say that I have really enjoyed reading your blog&lt;/p&gt;</description>
      <pubDate>Mon, 31 Oct 2011 10:31:47 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:6f167d3a-eca7-421c-9bc2-8719b90fd850</guid>
      <link>http://blog.objectmentor.com/articles/2009/03/16/tighter-ruby-methods-with-functional-style-pattern-matching-using-the-case-gem#comment-166282</link>
    </item>
    <item>
      <title>"Tighter Ruby Methods with Functional-style Pattern Matching, Using the Case Gem" by vendita scarpe mbt</title>
      <description>&lt;p&gt;real a good post , i am very like it , will come back again&lt;/p&gt;</description>
      <pubDate>Mon, 31 Oct 2011 10:29:55 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:dec40559-4361-4ba1-8589-dd159390eb79</guid>
      <link>http://blog.objectmentor.com/articles/2009/03/16/tighter-ruby-methods-with-functional-style-pattern-matching-using-the-case-gem#comment-166281</link>
    </item>
    <item>
      <title>"Tighter Ruby Methods with Functional-style Pattern Matching, Using the Case Gem" by flac converter</title>
      <description>&lt;p&gt;Thank you for sharing, I&#8217;ll definitely dig deeper into it.&lt;/p&gt;</description>
      <pubDate>Thu, 27 Oct 2011 02:48:09 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:04c06903-fc50-4bb7-b5d2-af541d551a64</guid>
      <link>http://blog.objectmentor.com/articles/2009/03/16/tighter-ruby-methods-with-functional-style-pattern-matching-using-the-case-gem#comment-164473</link>
    </item>
    <item>
      <title>"Tighter Ruby Methods with Functional-style Pattern Matching, Using the Case Gem" by ysbearing</title>
      <description>&lt;p&gt;Slewing bearing called slewing ring bearings, is a comprehensive load to bear a large bearing, can bear large axial, radial load and overturning moment.&lt;/p&gt;</description>
      <pubDate>Wed, 19 Oct 2011 03:11:46 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:5efbffa8-41bd-499b-9d91-ccc6dc6bc589</guid>
      <link>http://blog.objectmentor.com/articles/2009/03/16/tighter-ruby-methods-with-functional-style-pattern-matching-using-the-case-gem#comment-159433</link>
    </item>
    <item>
      <title>"Tighter Ruby Methods with Functional-style Pattern Matching, Using the Case Gem" by Ashley Bowling</title>
      <description>&lt;p&gt;Better late than never
Better safe than sorry
Better the Devil you know than the Devil you don&amp;#8217;t&lt;/p&gt;</description>
      <pubDate>Sat, 15 Oct 2011 15:40:43 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:201038ad-8ab3-406f-9370-e21e73736e3c</guid>
      <link>http://blog.objectmentor.com/articles/2009/03/16/tighter-ruby-methods-with-functional-style-pattern-matching-using-the-case-gem#comment-157209</link>
    </item>
    <item>
      <title>"Tighter Ruby Methods with Functional-style Pattern Matching, Using the Case Gem" by Evering2010</title>
      <description>&lt;p&gt;Thank you for sharing them with us , I think it&amp;#8217;s worth reading&lt;/p&gt;</description>
      <pubDate>Sat, 15 Oct 2011 04:08:53 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:2f05cb49-2cb6-4737-8cc7-79d398815d5e</guid>
      <link>http://blog.objectmentor.com/articles/2009/03/16/tighter-ruby-methods-with-functional-style-pattern-matching-using-the-case-gem#comment-157038</link>
    </item>
    <item>
      <title>"Tighter Ruby Methods with Functional-style Pattern Matching, Using the Case Gem" by christianlouboutin</title>
      <description>&lt;p&gt;All among us realise that if you MBT boots or shoes within get hold of, &lt;a href="http://www.louboutinchaussures-fr.com/jimmy-choo-jimmy-choo-sandales-39_36/" rel="nofollow"&gt;Jimmy Choo Sandales&lt;/a&gt;education-women&#8217; vertisements mbt tunisha providing may easily really encourages lymphatic circulation,&lt;a href="http://www.louboutinchaussures-fr.com/jimmy-choo-jimmy-choo-bottines-39_33/" rel="nofollow"&gt;Jimmy Choo Bottines&lt;/a&gt; you&#8217; chemical in all probability more significant receive boots or shoes clearance retail store as a result of MBT while it a good number of at no cost submitting in combination with MBT boots or shoes are almost always pay for and also profit designed notnax&lt;a href="http://www.canadagoosejakkedk.com" rel="nofollow"&gt;&lt;strong&gt;canada goose outlet&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;A particular low-priced MBT Nama Boots and shoes out of a number of online space boots and shoes plus boot footwear MBT great bargains preferred now in now would be to simply and even safely mbt sandals pay for consumers pay for progressively more over the internet&lt;a href="http://www.canadagoosejakkedk.com" rel="nofollow"&gt;&lt;strong&gt;canada goose jakke&lt;/strong&gt;&lt;/a&gt;, have MBT footwear and remaining grown to be a sample. MBT boots providing now, ways to explain any one prevent&lt;p&gt;&lt;a href="http://www.north-face-jakke.com/" rel="nofollow"&gt;&lt;em&gt;&lt;strong&gt;the north face&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;? Brand-new assumed to test a person's MBT boots pay for, generate a test? My wife and i reassurance any one, we have a special working experience&lt;p&gt;&lt;a href="http://www.north-face-jakke.com/" rel="nofollow"&gt;&lt;em&gt;&lt;strong&gt;North Face Denali Jakker Kvinder hoodie&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;.&lt;/code&gt;&lt;/pre&gt;</description>
      <pubDate>Fri, 16 Sep 2011 22:27:56 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:c0238edd-40c3-4836-a42c-d24fab6cd0fe</guid>
      <link>http://blog.objectmentor.com/articles/2009/03/16/tighter-ruby-methods-with-functional-style-pattern-matching-using-the-case-gem#comment-141507</link>
    </item>
    <item>
      <title>"Tighter Ruby Methods with Functional-style Pattern Matching, Using the Case Gem" by Uniformes De F&#250;tbol </title>
      <description>&lt;p&gt;I really like your article. Please keep on writing excellent posts. To find out more please go to 
&lt;a href="http://baratasfutbolcamiseta.es/" rel="nofollow"&gt;http://baratasfutbolcamiseta.es/&lt;/a&gt;
&lt;a href="http://baratasfutbolcamiseta.es/category.php?id=9" rel="nofollow"&gt;http://baratasfutbolcamiseta.es/category.php?id=9&lt;/a&gt;
&lt;a href="http://baratasfutbolcamiseta.es/goods.php?id=76" rel="nofollow"&gt;http://baratasfutbolcamiseta.es/goods.php?id=76&lt;/a&gt;
&lt;a href="http://www.camisetas-de-futbol.es/" rel="nofollow"&gt;http://www.camisetas-de-futbol.es/&lt;/a&gt;
&lt;a href="http://www.camisetas-de-futbol.es/category-66-b0-FIFA+del+Copa+del+Mundo.html" rel="nofollow"&gt;http://www.camisetas-de-futbol.es/category-66-b0-FIFA+del+Copa+del+Mundo.html&lt;/a&gt;
&lt;a href="http://www.camisetas-de-futbol.es/goods-4080-10+11+Holland+Tercel+Blanco+camiseta+del+futbol.html" rel="nofollow"&gt;http://www.camisetas-de-futbol.es/goods-4080-10+11+Holland+Tercel+Blanco+camiseta+del+futbol.html&lt;/a&gt;
&lt;a href="http://www.camisetasfutbolchina.es/" rel="nofollow"&gt;http://www.camisetasfutbolchina.es/&lt;/a&gt;
&lt;a href="http://www.camisetasfutbolchina.es/category-122-b0-Real+Madrid.html" rel="nofollow"&gt;http://www.camisetasfutbolchina.es/category-122-b0-Real+Madrid.html&lt;/a&gt;
&lt;a href="http://www.camisetasfutbolchina.es/goods-4605-11+12+England+Titular+Blando+camiseta+del+futbol.html" rel="nofollow"&gt;http://www.camisetasfutbolchina.es/goods-4605-11+12+England+Titular+Blando+camiseta+del+futbol.html&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Fri, 16 Sep 2011 07:20:44 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:f0aa30b0-3cec-4d6b-b5cd-a8c34623e5fa</guid>
      <link>http://blog.objectmentor.com/articles/2009/03/16/tighter-ruby-methods-with-functional-style-pattern-matching-using-the-case-gem#comment-141376</link>
    </item>
    <item>
      <title>"Tighter Ruby Methods with Functional-style Pattern Matching, Using the Case Gem" by dvd ripper</title>
      <description>&lt;p&gt;good post, i think so.Thank you!&lt;/p&gt;</description>
      <pubDate>Sun, 11 Sep 2011 07:16:54 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:2262d36b-aad4-454a-8a30-d40f1d8c9f1a</guid>
      <link>http://blog.objectmentor.com/articles/2009/03/16/tighter-ruby-methods-with-functional-style-pattern-matching-using-the-case-gem#comment-139210</link>
    </item>
    <item>
      <title>"Tighter Ruby Methods with Functional-style Pattern Matching, Using the Case Gem" by cheap beats by dre uk</title>
      <description>&lt;p&gt;good post&lt;/p&gt;</description>
      <pubDate>Sun, 28 Aug 2011 21:57:24 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:3e3961de-28dc-49c9-9d69-68d047c915dd</guid>
      <link>http://blog.objectmentor.com/articles/2009/03/16/tighter-ruby-methods-with-functional-style-pattern-matching-using-the-case-gem#comment-133650</link>
    </item>
    <item>
      <title>"Tighter Ruby Methods with Functional-style Pattern Matching, Using the Case Gem" by beats by dre store</title>
      <description>&lt;p&gt;I really enjoyed reading it and will certainly share this post with my friends&lt;a href="http://www.drdrebeatsheadphones-australia.com" rel="nofollow"&gt;high quality headphones&lt;/a&gt;
&lt;a href="http://www.drdrebeatsheadphones-australia.com" rel="nofollow"&gt;new design headphones&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Tue, 23 Aug 2011 03:06:08 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:1f346a2a-fe07-4999-8572-08cc8e6dbace</guid>
      <link>http://blog.objectmentor.com/articles/2009/03/16/tighter-ruby-methods-with-functional-style-pattern-matching-using-the-case-gem#comment-131649</link>
    </item>
    <item>
      <title>"Tighter Ruby Methods with Functional-style Pattern Matching, Using the Case Gem" by onlyshox</title>
      <description>&lt;p&gt;Fantastic post. Your post was that great, keep it up.&lt;/p&gt;</description>
      <pubDate>Mon, 22 Aug 2011 02:42:28 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:94f0ed86-d0e4-4118-a9c1-3a1c47de6074</guid>
      <link>http://blog.objectmentor.com/articles/2009/03/16/tighter-ruby-methods-with-functional-style-pattern-matching-using-the-case-gem#comment-131076</link>
    </item>
    <item>
      <title>"Tighter Ruby Methods with Functional-style Pattern Matching, Using the Case Gem" by Crystal Jewellery</title>
      <description>&lt;p&gt;Great post! Nice and informative, I really enjoyed reading it and will certainly share this post with my friends .  Learn everything  about  &lt;a href="http://www.jewelleryxy.com/what-is-cubic-zirconia.html" rel="nofollow"&gt;what is cubic zirconia&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Thu, 18 Aug 2011 13:09:54 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:57aea116-56ab-47ed-aae0-4a48b0a446f6</guid>
      <link>http://blog.objectmentor.com/articles/2009/03/16/tighter-ruby-methods-with-functional-style-pattern-matching-using-the-case-gem#comment-129507</link>
    </item>
    <item>
      <title>"Tighter Ruby Methods with Functional-style Pattern Matching, Using the Case Gem" by dentist in houston </title>
      <description>&lt;p&gt;This is an wonderful article which mentioned the important program code by using Tighter Ruby Methods .IT is really a helpful article. I like it so so.&lt;/p&gt;</description>
      <pubDate>Wed, 17 Aug 2011 22:10:14 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:05e68691-aa93-4e14-bb89-31b6019b9e75</guid>
      <link>http://blog.objectmentor.com/articles/2009/03/16/tighter-ruby-methods-with-functional-style-pattern-matching-using-the-case-gem#comment-129183</link>
    </item>
  </channel>
</rss>

