code

Its all just ones and zeroes isn't it? 
Filed under

tristate

 

An Option class in Scala with three states: Unknown, Known.Some, Known.None

Scala's library includes a class called Option which can be used to represent an optional value, instead of using null, it has two states: None and Some[T], so either it has a value, or it doesn't.

I needed a class to represent three states (tristate): Unknown (you don't know the value), Known.Some (you know the value), Known.None (you know there is no value).  An example of where you'd use this might be for a property like radioType of class car.  You might use a tristate value to indicate that you don't know the type of the radio on this car, or that you do know the type of radio, or that there is no radio.

Code:



/*
 * Similar to Option[T], but represents three states: known-some, known-none, and unknown
 */
sealed abstract class KnownUnknown[+T] extends Product {
  def isEmpty : Boolean
  def get : T
  
  def isDefined : Boolean = !isEmpty
}

/*
 * Represents the unknown state
 */
case object Unknown extends KnownUnknown[ Nothing ] {
  def isEmpty = true
  def get = throw new NoSuchElementException("Unknown.get")
}

/*
 * Represents the known state (either you know its Some(T) or its None)
 */
final case class Known[+T](_value : Option[T]) extends KnownUnknown[T] {
  if ( _value == null )
    throw new NullPointerException
  
  def this(value : T) = this(Some(value))
  
  def isEmpty = false
  def get = _value.get
}


And a few basic tests:



class KnownUnknownTest extends TestCase("KnownUnknown") {
  def testSome = {
    var value : KnownUnknown[Int] = null
    value = new Known(5)
    
    value match {
      case Known(known) =>
        known match {
          case Some(number) => assertEquals(5, number)
          case None => fail()
        }
      case Unknown => fail()
    }
    
    assertEquals(5, value.get)
  }
  
  def testNone = {
    var value : KnownUnknown[Int] = null
    value = new Known(None)
    
    value match {
      case Known(known) =>
        known match {
          case Some(number) => fail()
          case None =>  // good
        }
      case Unknown => fail()
    }
    
    try {
      value.get
    }
    catch {
      case e:NoSuchElementException => // good
      case _ => fail()
    }    
    
    assert(true) // so we get picked up as a test
  }

  def testUnknown = {
    var value : KnownUnknown[Int] = null
    value = Unknown
    
    value match {
      case Known(known) => fail()
      case Unknown => // good
    }
    
    try {
      value.get
    }
    catch {
      case e:NoSuchElementException => // good
      case _ => fail()
    }
    
    assert(true) // so we get picked up as a test
  }
}


Filed under  //   option   scala   tristate   ubuntu  

Comments [0]