1998 Spring
A <list-of-doors> is either
null
, or
(cons d lod)
,
d
is a <door>, and
lod
is a <list-of-doors>.
;; lod-handler: <list-of-door> --> ?? ;; A template, following from the data definition. ;; ; (define lod-handler ; (lambda (lod) ; (cond [(null? lod) ...] ; [(cons? lod) ...(door-handler (first lod))... ; ...(lod-handler (rest lod))...])))Of course, you could have used
else
instead
of asking cons?
;
asking the question not only lets you re-order the cases with
impunity, but in real life lets you add an error clause,
[else (error 'lod-handler "Unexpected argument ~s~n" lod)]
.
define-struct
s.
A <door> is either
(make-room name)
, or
(make-hallway name lod)
, or
(make-outside)
,
name
is a symbol
and lod
is a <list-of-doors>.
To get these constructors constructors known to Scheme, we write
(define-struct room (name)) (define-struct hallway (name lod)) (define-struct outside ())For the last case we could have used a constant symbol (perhaps
'outdoors
),
although it's perfectly fine to have a structure with zero fields.
The zero-argument structure is preferable because
outside?
automatically,
and more importantly
;; door-handler:--> ?? ;; A template, following from the data definition. ;; ; (define door-handler ; (lambda (d) ; (cond [(room? d) ...(room-name d)] ; [(hallway? d) ...(hallway-name d)... ; ...(lod-handler (hallway-lod d))...] ; [(outside? d) ...] ; [else (error 'door-handler "Unknown type of door, ~s~n" d)])))
We flesh out the templates for <door> and <list-of-doors>.
A natural way to represent whether or not we can reach the outside
is by returning a boolean value.
(It is also acceptable to return tokens like
'can-get-out
and 'locked-in
.
Notice though that in Scheme, it is a convention that
functions whose names end in ?
always return boolean.)
;; can-escape?:--> boolean ;; Does the door d lead to the outside? ;; (define door-handler (lambda (d) (cond [(room? d) #f] [(hallway? d) (hallway-leads-out? (hallway-lod d))] [(outside? d) #t] [else (error 'door-handler "Unknown type of door, ~s~n" d)])))
;; hallway-leads-out?: <list-of-doors> --> boolean ;; Can we get outside via any door in the hallway? ;; (define hallway-leads-out? (lambda (lod) (cond [(null? lod) #f] [(cons? lod) (or (door-handler (first lod)) (hallway-leads-out? (rest lod)))] [else (error 'hallway-leads-out "bad list-of-doors ~s~n" lod)])))A common bug was to not follow the template, and inside the <list-of-doors> handler, start dissecting the cases of the first door. This usually resulted in a bug where if the first door were a hallway, the answer just recurred on that hallway, ignoring all the rest of the rooms in the original input list.