Turbo Pascal 2.0 course cover
← Back to Modules
module
17

Your Own Types

Introduction

Warehouse is built of squares, and every square is one of a few things: a wall, a bit of floor, a goal, a crate. You could number them - 0 for a wall, 1 for floor - and remember which is which. Or you could tell Pascal what the things are called, and have it remember for you, and refuse to let a square be anything else. That is what your own types are for.

Enumerated Types

type
  Tile = (Wall, Floor, Goal, Crate);
var
  T: Tile;

This declares a new type, Tile, whose values are exactly the four names in brackets - in that order. A Tile variable can hold Wall, Floor, Goal or Crate, and nothing else:

T := Floor;
if T = Wall then ...

The names are new words in your program, as good as True and False.

Because the values have an order, several things you know from numbers work:

  • Ord(T) gives its position, counting from 0: Ord(Wall) is 0, Ord(Crate) is 3.
  • Succ and Pred give the next and previous values: Succ(Wall) is Floor.
  • Comparisons follow the order: Wall < Crate is true.
  • for runs through them: for T := Wall to Crate do, or downto.
  • case chooses on them.
  • And the type's name turns a number back into a value: Tile(3) is Crate.

They Cannot Be Printed

Turbo will not print an enumerated value: Writeln(T) is

Error 66: I/O are not allowed. Press <ESC>

The names are for you and the compiler; to show one, print its Ord, or - much better - write a procedure that shows each value as it should appear. That is this section's program, and in Warehouse it draws the board.

Subranges

A subrange is a type limited to part of another:

type
  Col = 1..20;
  Mark = 0..100;

A Col is an integer from 1 to 20. Subranges say what a variable is for - a column on a board of 20, a mark out of 100 - and, with range checking on, Turbo holds you to it.

Byte is a subrange Turbo already has, from 0 to 255, and it wraps like an integer: 255 plus 1 is 0.

Constants

A number that means something should have a name:

const
  Width = 20;
  Height = 16;
type
  Col = 1..Width;

The const section comes before type. A constant can be used anywhere its value could - in sums, in a subrange - and it cannot be changed: Width := 30 is Error 41. When the board grows to 24 wide, you change one line.

Range Checking

Here is a trap. With Turbo as it starts, nothing checks the limits. A Col variable will happily hold 50; C := 25 is not even an error when compiled; and Succ(Crate) gives a fifth, nameless tile with Ord 4. The limits you declared are documentation and nothing more.

Put this at the top of the program:

{$R+}

and Turbo checks assignments to subrange variables as the program runs. The first value out of range stops it:

Run-time error 91, PC=004E
Program aborted

and ESC shows you the assignment that did it. Borland's manual recommends {$R+} while a program is being developed, and taking it out once the program works, because the checking slows the program down.

The Code

program Tiles;
type
  Tile = (Wall, Floor, Goal, Crate);
var
  T: Tile;

procedure Show(What: Tile);
begin
  case What of
    Wall: Write('#');
    Floor: Write(' ');
    Goal: Write('.');
    Crate: Write('$');
  end;
end;

begin
  for T := Wall to Crate do
  begin
    Show(T);
    Writeln(' is tile ', Ord(T));
  end;
end.

These are the characters Warehouse will draw its board with: # for a wall, a space for floor, . for a goal and $ for a crate.

Starting from

Turbo freshly started, Y, a new work file called TILES.

What you should see

# is tile 0
  is tile 1
. is tile 2
$ is tile 3

The floor's line begins with its own character - a space.

Change One Thing

  • Change Show(T); to Writeln(T);. What does Turbo say?
  • Add a fifth value, Worker, to the end of the type, and change the loop to run to Worker. What is printed for it, and why?
  • Run the loop Crate downto Wall instead. What happens to the order?

Exercises

17.1 Declare Direction = (North, East, South, West) and write a function TurnRight that gives the next direction clockwise - with West turning back to North. Starting from North, turn right six times, printing Ord of each direction.

17.2 Declare Mark = 0..100, switch on range checking, set a Mark to 99 and add 2 to it. What happens?

17.3 Declare constants Width = 20 and Height = 16, and print how many squares a board that size has.

Worked solutions are in Appendix II.

When It Goes Wrong

SymptomCause
Error 66: I/O are not allowedWriting an enumerated value. Print its Ord, or show it through a case.
A variable holds a value outside its declared range{$R+} is not on; nothing checks.
Run-time error 91A value out of range with {$R+} on. ESC shows where.
Error 41 assigning to a constantConstants cannot change. Use a variable.
A case on your type does nothingThe value has no label - perhaps a value you added to the type later.

Summary

type Tile = (Wall, Floor, Goal, Crate); makes a type whose values are those names, in order; Ord, Succ, Pred, comparisons, for and case all work on it, but it cannot be printed. Subranges such as 1..20 limit a type; const names a value that never changes. Nothing is range-checked unless {$R+} is on, and then an out-of-range value is Run-time error 91.

Next

S18, Sets - "is this one of those?" in one test: the question Warehouse asks every time the worker moves.

Get the Newsletter

New guides, disk images and community finds, roughly once a quarter. No spam, we promise, this isn't Tatung's marketing department.
Your subscription could not be saved. Please try again.
Your subscription has been successful.

Newsletter

Subscribe to our newsletter and stay updated.

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.