Types
A booking always has a venue, a number of guests, and a fee. A record can hold those, but nothing stops one booking from forgetting its fee, or another from having 9000 guests in a hall for 500. A type writes down, once, what every booking has and what each field allows.
type Booking
venue: text
guests: number where 1..500
fee: USD
hall = Booking venue = "Town Hall", guests = 120, fee = 500 USD
say hall.venue
say hall.guests
Town Hall
120
type Booking names a kind of record. Each line under it is one field: a name, then :, then its kind, the same way a function writes a parameter. A field can have a range with where, as in Contracts.
Booking venue = ..., guests = ..., fee = ... makes a new booking. It reads like record, with the type’s name in place of the word record. A type’s name starts with a capital letter, so it stands apart from values.
Making a record of a type
Every field has to be there, and each one has to be the right kind. A long record can put one field on each line:
type Booking
venue: text
guests: number where 1..500
fee: USD
garden = Booking
venue = "Garden"
guests = 40
fee = 200 USD
say garden
venue: Garden
guests: 40
fee: 200 USD
A field that might not have a value is a maybe, and you write missing or found for it, as in Maybe:
type Guest
name: text
phone: maybe text
amina = Guest name = "Amina", phone = found "555-0101"
omar = Guest name = "Omar", phone = missing
say omar.name
Omar
Types in functions
A function can take a type, and give one back. Write the type’s name where a kind goes:
type Booking
venue: text
guests: number where 1..500
fee: USD
fn deposit(b: Booking) -> USD
return b.fee / 5
fn bigger(b: Booking, more: number) -> Booking
return Booking venue = b.venue, guests = b.guests + more, fee = b.fee
hall = Booking venue = "Town Hall", guests = 120, fee = 500 USD
say deposit(hall)
say bigger(hall, 30).guests
100 USD
150
A list of a type is written list of Booking. Everything in Asking for data works on it:
type Booking
venue: text
guests: number where 1..500
fee: USD
hall = Booking venue = "Town Hall", guests = 120, fee = 500 USD
garden = Booking venue = "Garden", guests = 40, fee = 200 USD
bookings = list hall, garden
say get venue of bookings where guests > 100
say sum fee of bookings
Town Hall
700 USD
The rules always hold
A field’s where is checked every time a record of the type is made. When the value is written right there, Quill finds the mistake before the program runs:
type Booking
venue: text
guests: number where 1..500
big = Booking venue = "Stadium", guests = 9000
Problem on line 5 of hall.quill:
big = Booking venue = "Stadium", guests = 9000
^^^^
A Booking takes guests from 1 through 500, but this one gives 9000.
Line 3 says guests where 1..500.
When the value is worked out while the program runs, making the record stops the program:
type Booking
venue: text
guests: number where 1..500
crowd = 400 + 200
big = Booking venue = "Stadium", guests = crowd
Problem on line 6 of hall.quill:
big = Booking venue = "Stadium", guests = crowd
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
A Booking takes guests from 1 through 500, but guests is 600.
A Booking can't be made with a value outside that range. Check the value before making the Booking.
A function that takes a Booking checks the rules too, so even a plain record with the same fields can’t bring a value outside the range into it. Inside the function, b.guests is always from 1 through 500.
Common mistakes
Every field has to be there:
type Booking
venue: text
guests: number
hall = Booking venue = "Town Hall"
Problem on line 5 of example.quill:
hall = Booking venue = "Town Hall"
^^^^^^^
This Booking is missing the field guests.
Every Booking has all of its fields. Add it, or use missing for a maybe field.
A misspelled field is found before the program runs:
type Booking
venue: text
guests: number
hall = Booking venue = "Town Hall", gests = 120
Problem on line 5 of example.quill:
hall = Booking venue = "Town Hall", gests = 120
^^^^^
A Booking has no field called gests.
Its fields are venue, guests.
Did you mean: guests
A type can’t hold itself, because that one would hold another, and so on forever. Hold something that names the other one, like its id:
type Person
name: text
manager: maybe Person
Problem on line 3 of example.quill:
manager: maybe Person
^^^^^^^^^^^^
A Person can't hold a Person inside it, because that one would hold another, forever.
Hold something that names the other Person instead, like its id.
quill explain shows what a type line means. On type Booking, it lists each field and when its range is checked.
Try it
- Write
type Studentwithname: textandscore: number where 0..100. Make two students andsayeach one. - Make a student with a score of
120and read what Quill says. - Write
fn passed(s: Student) -> true/falsethat gives back whether the score is 50 or more. - Put your students in a list, and
say get name of students where score >= 50.