This document describes how to utilize the design recipe for the "at-zero?" function discussed in class, which tests whether an input posn is the origin.

Data

The data input to at-zero? is a posn. Since we already have a data definition for posns (they're provided by DrRacket), we don't need to write anything here. If we were working with our own invented data type here (like the "animal" type discussed in class), we'd want to write a data definition for the data type before writing functions that use it.

Signature, Purpose, Header

We start by writing down these three things. The first two are Racket comments, the third is a "stub" function we'll augment with the function body later:

So at this point in the design recipe, we've written down:

; at-zero? : posn -> boolean
; returns whether the input posn is the origin
(define (at-zero? p) (...))

Examples

Here, we write down a handful of examples of what our function should return for given inputs. Typically, I do this by writing check-expects at the end of the function (and then the "tests" step below is already done).

See below for the snippet of code we've written after including the tests:

; at-zero? : posn -> boolean
; returns whether the input posn is the origin
(define (at-zero? p) (...))
(check-expect (at-zero? (make-posn 0 0)) true)
(check-expect (at-zero? (make-posn 0 1)) false)
(check-expect (at-zero? (make-posn 1 0)) false)
(check-expect (at-zero? (make-posn 1 1)) false)

Template

Our input data is posns. Posns are a struct with two data elements x and y, so our template includes the selectors for those two fields. So we type out the following comment:

; template
; (... (posn-x p) ...
; ... (posn-y p) ...)

We also copy this template as a starter for the body of our code. Now, in the future you might simply write the template in the function body, and not include the comment. However, for homework #2 you should include the comment.

So at this point, we have the following code:

; at-zero? : posn -> boolean
; returns whether the input posn is the origin
; template
; (... (posn-x p) ...
; ... (posn-y p) ...)
(define (at-zero? p) (
   ... (posn-x p) ...
   ... (posn-y p) ...)
   )
(check-expect (at-zero? (make-posn 0 0)) true)
(check-expect (at-zero? (make-posn 0 1)) false)
(check-expect (at-zero? (make-posn 1 0)) false)
(check-expect (at-zero? (make-posn 1 1)) false)

Body

Now we fill in the function body, testing whether each dimension of the posn is zero. As a fantastic convenience, the selectors we need are already in the function body. When we're done, we output the following:

; at-zero? : posn -> boolean
; returns whether the input posn is the origin
; template
; (... (posn-x p) ...
; ... (posn-y p) ...)
(define (at-zero? p)
  (and
     (= (posn-x p) 0)
     (= (posn-y p) 0)
   )
)
(check-expect (at-zero? (make-posn 0 0)) true)
(check-expect (at-zero? (make-posn 0 1)) false)
(check-expect (at-zero? (make-posn 1 0)) false)
(check-expect (at-zero? (make-posn 1 1)) false)

Tests

We have tests in place because we wrote down our examples in the form of tests. When we run the above code in DrRacket, we see "All 4 tests passed!" Victory is ours.