Practical programs need data structures and Hope has two standard kinds already built in. The simplest kind corresponds to a Pascal record. We can bind a fixed number of objects of any type together into a structure called a tuple, for example:
( 2, 3 )or
( 'a', true )are tuples of type num # num and char # truval respectively. We use tuples when we want a function to define more than one value. Here's one that defines the time of day given the number of seconds since midnight:
dec time24 : num -> num # num # num ; --- time24 ( s ) <= ( s div 3600, s mod 3600 div 60, s mod 3600 mod 60 ) ;div is the built-in integer division function and mod gives the remainder after integer division. If we type an application of time24 at the terminal, the result tuple and its type will be printed on the screen in the usual way:
time24 ( 45756 ) ; ( 12,42,36 ) : ( num # num # num )The second standard data type, called a list, corresponds roughly to a one-dimensional array in Pascal. It can contain any number of objects (including none at all) but they must all be the same type. We can write expressions in our programs that represent lists, such as:
[ 1, 2, 3 ]which is of type list ( num ). There are two standard functions for defining lists. The infix operator :: (read as `cons') defines a list in terms of a single object and list containing the same type of object, so
10 :: [ 20, 30, 40 ]defines the list:
[ 10, 20, 30, 40 ]Don't think of :: as adding 10 to the front of [ 20, 30, 40 ]. It really defines a new list [ 10, 20, 30, 40 ] in terms of two other objects without changing their meaning, rather in the same way that 1 + 3 defines a new value of 4 without changing the meaning of 1 or 3.
The other standard list function is nil, which defines a list with no elements in it. We can represent every list by an expression consisting of applications of :: and nil. When we write an expression like:
[ a + 1, b - 2, c * d ]it's considered to be a shorthand way of writing:
a + 1 :: ( b - 2 :: ( c * d :: nil ) )There's also a shorthand way of writing lists of characters. The following three expressions are all equivalent:
"cat" [ 'c', 'a', 't' ] 'c' :: ( 'a' :: ( 't' :: nil ) )When the result of a Hope program is a list, it's always printed out in the concise bracketed notation; if it's a list of characters, it's printed in quotes.
Every data type in Hope is defined by a set of primitive functions like :: and nil. They're called constructor functions, and aren't defined by recursion equations. When we defined a tuple, we were actually using a standard constructor called , (read as `comma'). Later on we'll see how constructors are defined for other types of data.