How to Design ProgramsHow to (in Scheme):• represent datavariantstrees and lists• write functions that process the dataSee alsohttp://www.htdp.org/1Running Example: GUIsPick a fruit:AppleBananaCoconutOk CancelPossible programs:• Can click?• Find a label• Read screen2Representing GUIsPick a fruit:AppleBananaCoconutOk Cancel• labelsa label string• buttonsa label stringenabled state• listsa list of choice stringsselected item(define-type GUI [label (text string?)] [button (text string?)(enabled? boolean?)] [choice (items (listof string?))(selected integer?)])7Read Screen; read-screen : GUI -> list-of-string(define (read-screen g) (type-case GUI g [label (t) (list t)] [button (t e?) (list t)] [choice (i s) i])) (test (read-screen (label "Hi"))'("Hi"))(test (read-screen (button "Ok" true))'("Ok"))(test (read-screen (choice '("Apple" "Banana") 0))'("Apple" "Banana"))8Assemblings GUIsPick a fruit:AppleBananaCoconutOk Cancel• label• buttons• lists• vertical stackingtwo sub-GUIs• horizontal stackingtwo sub-GUIs(define-type GUI [label (text string?)] [button (text string?)(enabled? boolean?)] [choice (items (listof string?))(selected integer?)] [vertical (top GUI?)(bottom GUI?)] [horizontal (left GUI?)(right GUI?)])12Assemblings GUIsPick a fruit:AppleBananaCoconutOk Cancel• label• buttons• lists• vertical stackingtwo sub-GUIs• horizontal stackingtwo sub-GUIs(define gui1 (vertical(horizontal(label "Pick a fruit:")(choice '("Apple" "Banana" "Coconut")0))(horizontal(button "Ok" false)(button "Cancel" true))))13Read Screen; read-screen : GUI -> list-of-string(define (read-screen g) (type-case GUI g [label (t) (list t)] [button (t e?) (list t)] [choice (i s) i] [vertical (t b) (append (read-screen t)(read-screen b))] [horizontal (l r) (append (read-screen l)(read-screen r))])) ; ... earlier test cases ...(test gui1'("Pick a fruit:""Apple" "Banana" "Coconut""Ok" "Cancel"))14Function and Data Shapes Match(define-type GUI [label (text string?)] [button (text string?)(enabled? boolean?)] [choice (items (listof string?))(selected integer?)] [vertical (top GUI?)(bottom GUI?)] [horizontal (left GUI?)(right GUI?)])(define (read-screen g) (type-case GUI g [label (t) (list t)] [button (t e?) (list t)] [choice (i s) i] [vertical (t b) (append (read-screen t)(read-screen b))] [horizontal (l r) (append (read-screen l)(read-screen r))]))16Design Steps• Determine the representationdefine-type• Write examplestest• Create a template for the implementationtype-case plus natural recursion,check shape!• Finish implementation case-by-casethe is usually the interesting part• Run tests17Enable ButtonThe name argument is “along for the ride”:; enable-button : GUI string -> GUI(define (enable-button g name) (type-case GUI g [label (t) g] [button (t e?) (cond[(equal? t name) (button t true)][else g])] [choice (i s) g] [vertical (t b) (vertical (enable-button t name)(enable-button b name))] [horizontal (l r) (horizontal (enable-button l name)(enable-button r name))]))...(test (enable-button gui1 "Ok")(vertical(horizontal (label "Pick a fruit:")(choice '("Apple" "Banana" "Coconut") 0))(horizontal (button "Ok" true)(button "Cancel" true))))18Show Depth(test (show-depth HelloOk Cancel)1 Hello2 Ok 2 Cancel)19Show DepthTemplate:(define (show-depth g) (type-case GUI g [label (t) ...] [button (t e?) ...] [choice (i s) ...] [vertical (t b) ... (show-depth t)... (show-depth b) ...] [horizontal (l r) ... (show-depth l)... (show-depth r) ...]))20Show DepthTemplate:(define (show-depth g) (type-case GUI g [label (t) ...] [button (t e?) ...] [choice (i s) ...] [vertical (t b) ... (show-depth t)... (show-depth b) ...] [horizontal (l r) ... (show-depth l)... (show-depth r) ...]))(show-depth Ok)→ 0 Ok21Show DepthTemplate:(define (show-depth g) (type-case GUI g [label (t) ...] [button (t e?) ...] [choice (i s) ...] [vertical (t b) ... (show-depth t)... (show-depth b) ...] [horizontal (l r) ... (show-depth l)... (show-depth r) ...]))(show-depth Ok Cancel)→ ... 0 Ok ... 0 Cancel ...22Show DepthTemplate:(define (show-depth g) (type-case GUI g [label (t) ...] [button (t e?) ...] [choice (i s) ...] [vertical (t b) ... (show-depth t)... (show-depth b) ...] [horizontal (l r) ... (show-depth l)... (show-depth r) ...]))recursion results don’t have the right labels...23Show DepthThe n argument is an accumulator:; show-depth-at : GUI num -> GUI(define (show-depth-at g n) (type-case GUI g [label (t) (label (prefix n t))] [button (t e?) (button (prefix n t) e?)] [choice (i s) g] [vertical (t b) (vertical (show-depth-at t (+ n 1))(show-depth-at b (+ n 1)))] [horizontal (l r) (horizontal (show-depth-at l (+ n 1))(show-depth-at r (+ n 1)))])) ; show-depth : GUI -> GUI(define (show-depth g) (show-depth-at g 0))24Programming With ListsSometimes you can use map, ormap, etc.; has-label? : list-of-string string -> bool(define (has-label? l s) (ormap (lambda (e) (string=? e s)) l)) (test (has-label? empty "Banana") false)(test (has-label? '("Apple" "Banana") "Banana")true)25Programming With ListsSometimes you can use map, ormap, etc.; has-label? : list-of-string string -> bool(define (has-label? l s) (ormap (lambda (e) (string=? e s)) l)) (test (has-label? empty "Banana") false)(test (has-label? '("Apple" "Banana") "Banana")true)Otherwise, the general design process works forprograms on lists using the following data definition:; A list-of-string is either; - empty; - (cons string list-of-string)26Programming With Lists; A list-of-string is either; - empty; - (cons string list-of-string); has-label? : list-of-string string -> bool(define (has-label? l s) (cond [(empty? l) ...] [(cons? l) ... (first l)... (has-label? (rest l) s) ...]))29Programming With Lists; A list-of-string is either; - empty; - (cons string list-of-string); has-label? : list-of-string string -> bool(define (has-label? l s) (cond [(empty? l) false] [(cons? l) (or (string=? (first l) s)(has-label? (rest l)
View Full Document