Emulating Smalltalk's Conditionals in Ruby

If you follow my blog, you know that I enjoy emulating language features from other languages (like Python) in pure-Ruby. On the flight back from London, I read through Smalltalk Best Practice Patterns, and was reminded that Smalltalk doesn't have built-in conditionals.

Instead, they use method calls (aka message sends) to do the heavy lifting:

anObject isNil  
  ifTrue:  [ Transcript show: 'true'. ]
  ifFalse: [ Transcript show: 'false'. ].

In contrast, the typical way to do that in Ruby is:

if an_object.nil?  
  puts "true"
else  
  puts "false"
end  

However, the Smalltalk approach is fully compatible with Ruby's pure-OO approach (which is, in fact, inherited from Smalltalk in the first place). So why not be able to do:

(an_object.nil?).
  if_true  { puts "true" }.
  if_false { puts "false" }

In Ruby, unlike Smalltalk, message sends use a ".", so we need to use periods between the message sends to link them together. With that exception, the semantics of the two languages are roughly identical. And, as usual, the implementation in Ruby is pretty straight-forward:

class Object  
  def if_true
    yield
    self
  end

  def if_false
    self
  end
end

class NilClass  
  def if_true
    self
  end

  def if_false
    yield
    self
  end
end

class FalseClass  
  def if_true
    self
  end

  def if_false
    yield
    self
  end
end  

In Ruby, false and nil are "falsy", while all other values are "truthy". Since everything in Ruby inherits from Object, we can simply define iftrue and iffalse on Object, FalseClass, and NilClass. If the block should be called (iftrue on truthy values, or iffalse on falsy values), we yield. In all cases, we return "self" so that we can chain iftrue to iffalse. And that's it.

Of course, this means extending core classes, which some people are shy about doing, but it does mirror the semantics of Smalltalk.