9.2 Examples of types that are not classes

Later in our development of the time library, we shall find it useful to define a new type that represents nonnegative integers:

// Define nonnegative integers as integers that are >= zero
define constant <nonnegative-integer> = limited(<integer>, min: 0);

We can use a nonclass type as a parameter specializer of a method, or as the type of a return value:

define method encode-total-seconds 
    (max-unit :: <nonnegative-integer>, 
     minutes :: <nonnegative-integer>, 
     seconds :: <nonnegative-integer>) 
 => (total-seconds :: <nonnegative-integer>)
  ((max-unit * 60) + minutes) * 60 + seconds;
end method encode-total-seconds; 

To see how we use <nonnegative-integer> in the time library, see Section 10.2.2, page 120.

We can define a type whose only member is the false value, #f:

singleton(#f);

We can define a type that is the union of the false value and <integer>:

type-union(singleton(#f), <integer>);

We can make it convenient for people to create new types like the one defined in the preceding code. The new type is the union of the false value and the argument to the method:

define method false-or (other-type :: <type>) => (combined-type :: <type>)
  type-union(singleton(#f), other-type);
end method false-or;

False-or types are useful as the type of slots. Note that a slot can be uninitialized. Once a slot receives a value, however, it will always have a value: There is no way to return a slot to the uninitialized state. Sometimes it is useful to store in a slot a value that means none. Later on in our development of the airport example, we use a false-or type as the type of a slot that stores "the next vehicle, if there is one." If there is no next vehicle, the slot contains #f. We create the type by calling false-or(<vehicle>), and use the result as the type of the slot. Note that, if the type of the slot were just <vehicle>, we could not store #f in the slot, and there would be no way to represent none.

You can use type-union and singleton together to define a type that is an enumeration of multiple-choice objects. For example,

define constant <latitude-direction> 
  = type-union(singleton(#"north"), singleton(#"south"));

The <latitude-direction> type has two valid values: the keywords #"north" and #"south". For an explanation of how we could use that type to enforce the correct values of a latitude slot, and for information about the performance of enumerations, see Section 19.5, page 318.