An Alley-OOP for If

Ruby takes a unique approach to conditional evaluation: All objects are equivalent to true except nil and false. No doubt this is a more object-oriented approach than, say, C++’s use of 0 as false, but it’s far from the ideal of OOP all the way down, as any Smalltalker can attest.

Consider the following case. For a while now I have wanted in my arsenal of Ruby classes a NullClass defined basically as:

  class NullClass < NilClass
    def method_missing(*a)
      self
    end
  end
 
  NULL = NullClass.new
 
  def null
    NULL
  end

This object would greatly benefit fluent interfaces. Instead of returning nil, such interfaces could return null, and no error would be thrown when invoking any method against it.

  obj = null
  obj.it.does.not.matter  #=> null

Unfortunately null is not very viable in Ruby because null still evaluates as true when used as the expression of a condition. The fact remains, Ruby is hardcoded to see only the singleton instances of NilClass and FalseClass as false.

I’ve requested that NullClass be added to core Ruby in the past (as of yet to no avail) and though I still would like to see it included, it may be better still to take an altogether object-oriented approach to conditions –in the spirit of Smalltalk. This would allow us to freely create “false” objects, like the NullClass, ourselves.

The adoption of such a capability does not require the odd syntax used by Smalltalk (ifTrue / ifFalse). Rather, it can take an approach more akin to Ruby’s own case statements. As with case’s use of #===, a particular method would be used to evaluate the “truthiness” of a value. This would apply for all types of conditions: while, until, etc.

To clarify, let’s say this special method is simply called #if, then…

  class IfExample
    attr :if
    def initialize(@if)
      @if = if
    end
  end
 
  x = IfExample.new(false)
 
  if x
    "Yes"
  else
    "No"
  end

The result of this condition would be "No".

While it may not be an earth shattering adjustment, the additional flexibility opens up some interesting doors. Not only would classes like the previously mentioned NullClass become possible, but conditions themselves become dynamically controllable.

For example, it would allow method probes to fully map method signatures (the Halting Problem not withstanding). This is not currently possible in Ruby because a probe cannot pretend to evaluate to false in order to walk through the false side of a condition.

The idea would require some getting used to –after all a simple if-statement would no longer do what we Rubyists presently take for granted. But then, that’s the nature of progress, is it not?