How to create an Object who act as a False in Ruby

Unfortunately, this is not possible.

This is one of those annoying cases where Ruby is not object-oriented. In OO, it must be possible for one object to simulate another (in fact, depending on whom you ask, this is the very definition of OO – remember that OO came out of simulation), but it is not possible to build an object which simulates false.

This is because, in Ruby, conditional control structures are baked into the language and don’t translate into message sends, whereas in other OO languages they are just regular message sends (or at least translate into message sends, just like for in Ruby translates into each). For example, in Smalltalk, Booleans are actually implemented using the Church encoding of Booleans you know from Lambda Calculus, and translated to Ruby they look a bit like this:

class FalseClass
  def if(&block)
    # do nothing
  end

  def if_then_else(then_lambda, else_lambda)
    else_lambda.()
  end

  def not
    true
  end

  def and(&block)
    self
  end

  def or(&block)
    block.()
  end
end

And TrueClass is just the mirror image:

class TrueClass
  def if(&block)
    block.()
  end

  def if_then_else(then_lambda, else_lambda)
    then_lambda.()
  end

  def not
    false
  end

  def and(&block)
    block.()
  end

  def or(&block)
    self
  end
end

And then, instead of something like

if 2 < 3 then foo end
if 2 < 3 then bar else baz end

You would have

(2 < 3).if { foo }
(2 < 3).if_then_else(-> { bar }, -> { baz })

# using the new keyword arguments in Ruby 2.0, it almost reads like Smalltalk:
class FalseClass
  def if(then: -> {}, else: -> {})
    else.()
  end
end

class TrueClass
  def if(then: -> {}, else: -> {})
    then.()
  end
end

(2 < 3).if(then: -> { bar }, else: { baz })

That way, you can easily create an object which simulates false simply by implementing the respective methods.

In other cases, where some object really absolutely must be an instance of a specific class and not just speak the correct protocol, Ruby provides an escape hatch. For example, if a method really requires an Array as an argument, then it will first try to call to_ary to at least give you a chance to convert your object into an Array. The same goes for to_str, to_int, to_proc, to_float etc. But there is no equivalent to_bool protocol.

Leave a Comment