On this page:
1 Templates
2 Using process-month to design functions
3 Using process-month-format to design functions
4 Using process-date-order to design functions

Lab 3: Using templates

You may submit this lab to lab3 on Handin (this is optional).

Important: Whenever you write a function in this class, follow the design recipe. You will be graded accordingly.

1 Templates

In lecture this week, we defined a data type (an enumeration, to be specific) named TrafficLight for the purpose of representing the state of a traffic light. Here it is again:

; A TrafficLight is one of:
; - "green"
; - "yellow"
; - "red"

Afterwards, we defined two different functions which processed TrafficLight: draw-traffic-light and next-traffic-light. Recall what the templates (from Step 4 of the design recipe) looked like for each function:

; draw-traffic-light : TrafficLight -> Image
; draws a picture of a traffic light in the given state
(define (draw-traffic-light tl)
  (cond
    [(string=? "green" tl)  ...]
    [(string=? "yellow" tl) ...]
    [(string=? "red" tl)    ...]))
 
; next-traffic-light : TrafficLight -> TrafficLight
; returns the next TrafficLight
(define (next-traffic-light tl)
  (cond
    [(string=? "green" tl)  ...]
    [(string=? "yellow" tl) ...]
    [(string=? "red" tl)    ...]))

Notice that after the header, they are very similar. This situation happens so often that, for the sake of convenience, we may write down a template just based on the data definition, which we can then copy and paste whenever we define a function which processes that data type.

For example, the template for processing a TrafficLight is

; process-traffic-light : TrafficLight -> ...
(define (process-traffic-light tl)
  (cond
    [(string=? "green" tl)  ...]
    [(string=? "yellow" tl) ...]
    [(string=? "red" tl)    ...]))

Note that “process-traffic-light” here is just a place holder for an actual function name. Above we have replaced “process-traffic-light” with “draw-traffic-light” and “next-traffic-light”. The name “process-traffic-light” is not intended to be used as an actual function name. It is just the name of the template. (DrRacket understands templates: the above code runs.)

Exercise 1. Here is the data definition of a Month:

; A Month is one of:
; - "January"
; - "February"
; - "March"
; - "April"
; - "May"
; - "June"
; - "July"
; - "August"
; - "September"
; - "October"
; - "November"
; - "December"

Finish writing the template process-month:

; process-month : Month -> ...
(define (process-month m) ...)

Exercise 2. Here is the definition of a MonthFormat:

; A MonthFormat is one of:
; - "long"
; - "short"

Finish writing process-month-format:

; process-month-format : MonthFormat -> ...
(define (process-month-format f) ...)

Exercise 3. Here is the definition of a DateOrder:

; A DateOrder is one of:
; - "MDY"
; - "DMY"

Finish writing process-date-order:

; process-date-order : DateOrder -> ...
(define (process-date-order o) ...)
2 Using process-month to design functions

Exercise 4. Finish designing the following function:

; next-month : Month -> Month
; returns the month that comes after the given one
(define (next-month m) ...)
 
(check-expect (next-month "September") "October")
(check-expect (next-month "December") "January")

When you get to Step 4 of the design recipe, copy the body of process-month and paste it as the body of next-month.

Exercise 5. Finish designing the following function:

; fall? : Month -> Boolean
; decides whether the given month is between September and November

When you get to Step 4 of the design recipe, copy the body of process-month and paste it as the body of fall?.

3 Using process-month-format to design functions

Exercise 6. Finish designing the following function:
; format-month : Month MonthFormat -> String
; abbreviates Month to three letters or not
(define (format-month m f) ...)
 
(check-expect (format-month "November" "long") "November")
(check-expect (format-month "November" "short") "Nov")

Notice that format-month has two inputs. Both inputs are enumerations, Month and MonthFormat, which have templates, process-month and process-month-format. Which one do we use? Or do we use both?

It depends on the actual function we’re defining. For format-month, on the one hand, it is necessary to process the MonthFormat. On the other hand, it is possible to avoid processing the Month: we can view the Month as a mere String and use the substring function.

When you get to Step 4 of the design recipe, copy the body of process-month-format and paste it as the body of format-month. Then change the right-hand sides of the cond clauses of format-month’s template to include the argument m: the right-hand sides should look like (... m ...).

4 Using process-date-order to design functions

Exercise 7. Use format-month to design the following function:

; A Year is a non-negative integer
 
; A Day is an integer which is at least 1 but at most 31
 
; year-month-day->date : Year Month Day DateOrder MonthFormat -> String
; produces a date as a string
; given: 1936 "November" 12 "MDY" "long"   expect: "November 12, 1936"
; given: 1936 "November" 12 "MDY" "short"  expect: "Nov 12, 1936"
; given: 1936 "November" 12 "DMY" "long"   expect: "12 November 1936"
; given: 1936 "November" 12 "DMY" "short"  expect: "12 Nov 1936"
(define (year-month-day->date y m d o f) ...)

Use string-append and number->string.

Again, we must make a decision about which inputs to process as enumerations: the options include the Month, the DateOrder, and the MonthFormat. Note that the Month and the MonthFormat will simply be passed to format-month to produce a useful string. So it remains only to process the DateOrder.

When you get to Step 4 of the design recipe, copy the body of process-date-order and paste it as the body of year-month-day->date. Then change the right-hand sides of the cond clauses of year-month-day->date’s template to include the additional arguments: the right-hand sides should look like (... y ... m ... d ... f ...).