500 likes | 510 Views
Learn about the new symbol and char data types in programming, their spelling rules, built-in functions, and how to use them in code. Explore examples and exercises to deepen your understanding.
E N D
TeachScheme, ReachJava Adelphi University Tuesday morning June 23, 2009
A new type: symbol "foo-bar" is a string 'foo-bar is a symbol(yes, no closing apostrophe) Spelling rule: basically the same as a variable or function name, but preceded with apostrophe Built-in function ; symbol=? : symbol symbol -> boolean
Mouse handlers • Contract : model num(x) num(y) symbol -> model • Events: 'button-down, 'button-up, 'drag, 'move, 'wheel-up, 'wheel-down, 'enter, 'leave … • Typically, one or two "interesting" events and an "anything else" category. • Code structure: cond with one or two (symbol=? ... …) questions and an else
Example mouse handler Exercise 18.2.1 in book: ; add-dot-on-mouse-down : image(old) num(x) num(y) symbol(event) -> image (check-expect (add-dot-on-mouse-down BACKGROUND 35 10 'button-down)(place-image DOT 35 10 BACKGROUND)) (check-expect (add-dot-on-mouse-down BACKGROUND 35 10 'button-up)BACKGROUND)
Example mouse handler (define (add-dot-on-mouse-down old x y event); old image; x, y numbers; event symbol(cond [(symbol=? event 'button-down) (place-image DOT x y old)] [else old] ; ignore this event))
A new type: char "x" is a string #\x is a char 7 is a number "7" is a string #\7 is a char Built-in functions ; char=? : char char -> boolean ; string-ref : string number -> char ; make-string : char number -> string ; others (see Help Desk or Chap. 19 of book)
A function using char ; starts-with-M? : string -> boolean (check-expect (starts-with-M? "a") false) (check-expect (starts-with-M? "M") true) (check-expect (starts-with-M? "abcMdef") false) (check-expect (starts-with-M? "") false) (check-expect (starts-with-M? "Morgan") true)
A function using char (define (starts-with-M? str); str string; (string-ref str 0) char(char=? (string-ref str 0) #\M)) Mostly works, but crashes on empty string!
A function using char (define (starts-with-M? str); str string; (string-ref str 0) char, if str non-empty(cond [(= (string-length str) 0) false] [else (char=? (string-ref str 0) #\M)])) Passes all test cases… but do we really need cond?
A function using char (define (starts-with-M? str); str string; (string-ref str 0) char, if str non-empty(and (> (string-length str) 0) (char=? (string-ref str 0) #\M))) Slightly shorter and simpler
A new type: key A key is either a symbol or a char(Specifically, 'left, 'right, 'down, 'up, 'escape, 'f1, 'home, 'release, …) Built-in function ; key=? : key key -> boolean
Example Write an animation of a calendar that starts at the middle of the screen and moves left or right in response to left and right arrow keys on the keyboard Ex. 19.2.1 in book
Animation: model & handlers Let's use a number as the model, representing the x coordinate (the y coordinate will be fixed at, say, 50) We need a redraw handler ; calendar-at-x: number -> image and a key handler ; handle-key: number char-or-symbol -> number
Animation: redraw handler ; calendar-at-x: number -> image (define (calendar-at-x x); x number(place-image calendar x 50 BACKGROUND)) (check-expect (calendar-at-x 27) (place-image calendar 27 50 BACKGROUND)) (check-expect (calendar-at-x 193) (place-image calendar 193 50 BACKGROUND))
Animation: key handler Model is a number representing x coordinate Want to respond to left, right arrow keys ; handle-key : number(x) key -> number (check-expect (handle-key 10 #\D) 10) (check-expect (handle-key 10 'left) 9) (check-expect (handle-key 10 'right) 11) (check-expect (handle-key 10 'up) 10)
Animation: key handler (define (handle-key x key); x number; key key(cond [(key=? key 'left) …] [(key=? key 'right) …] [else …]))
Animation: key handler (define (handle-key x key); x number; key key(cond [(key=? key 'left) (- x 1)] [(key=? key 'right) (+ x 1)] [else x]))
Running the animation (define WIDTH 300) (define HEIGHT 100) (define BACKGROUND(rectangle WIDTH HEIGHT "solid" "white")) (run-animation WIDTH HEIGHT(/ WIDTH 2) 1(on-redraw calendar-at-x)(on-key handle-key))
Defining a type "by choices" • Type = "this string or that string or …" • Type = "this range of numbers or that range of numbers or …" • Type = "this type or that type or …" • Test cases: at least one for each category of input or output
Code for definition by choices • A cond w/ N branches, where N is the number of categories in the input type • For strings, usually use string=? • For numbers, <, >, <=, >=, =, … • For symbols, symbol=? • For chars, char=? • For types, …?
Discriminator functions (built-in) • number? : anything -> boolean • string? : anything -> boolean • image? : anything -> boolean • symbol? : anything -> boolean • char? : anything -> boolean • etc. Tell whether something is of the specified type
Example Write a function big? that takes in a number or a string or an image. Numbers > 1000 are "big"; strings longer than 10 characters are "big"; images with height* width > 10000 are "big".
Contract & data analysis ; big? : number, string, or image -> boolean ; Data analysis: input is either number, string, or image ; In each case, it's broken down into two sub-categories
Test cases (check-expect (big? 347) false) (check-expect (big? 1000) false) (check-expect (big? 1200) true) (check-expect (big? "alison") false) (check-expect (big? "passphrase") false) (check-expect (big? "brontosaurus") true) (check-expect (big? calendar) false) (check-expect (big? (rectangle 200 50 "solid" "purple")) false) (check-expect (big? (ellipse 200 60 "outline" "chartreuse")) true)
Skeleton & inventory (define (big? thing); thing a string, number, or image)
Body, first draft (define (big? thing); thing string, number, or image(cond [ q a ] [ q a ] [ q a ]))
Body, second draft (define (big? thing); thing string, number, or image(cond [(string? thing) a ] [(number? thing) a ] [(image? thing) a ]))
Body, third draft (define (big? thing); thing string, number, or image(cond [(string? thing) (> (string-length thing) 10)] [(number? thing)(> thing 1000)] [(image? thing)(> (* (image-width thing) (image-height thing)) 10000)]))
Example: animation using type choice • Key handler that treats all chars one way, all symbols another way • Exercises 20.4.1, 20.4.2 in book
Recall left/right arrow animation • Could obviously have picture move up or down, rather than left or right • Could have circle of radius that increases or decreases • etc. • How about a picture that moves up, down, left, or right?Problem: need to "remember" both x and y coordinates
Definition by parts Sometimes several related data need to be passed around together, e.g. • name, SSN, and salary of employee • x and y coordinates of 2-D point • name, length, and favorite food of boa-constrictor Scheme allows you to define a new data type with several "parts"
A predefined struct There's a built-in type named posn, which has two parts x and y. Built-in functions ; make-posn : number(x) number(y) -> posn ; posn-x : posn -> number ; posn-y : posn -> number ; posn? : anything -> boolean
For those who know Java… • make-posnis a constructor. • posn-xandposn-y are getter methods. • There are also setter methods, but we'll get to them later.
Using posns "Examples of the posn type:" (make-posn 3 5) (make-posn 12 -7) (define here (make-posn 14 9)) (check-expect (posn-x here) 14) (check-expect (posn-y here) 9)
Writing functions on posns Almost any function that takes in a posn looks like (define (function-on-posn where) ) (the "skeleton" step of the recipe)
Writing functions on posns Almost any function that takes in a posn looks like (define (function-on-posn where); where posn ) (the "inventory" step of the recipe)
Writing functions on posns Almost any function that takes in a posn looks like (define (function-on-posn where); where posn; (posn-x where) number; (posn-y where) number ) (the "inventory" step of the recipe, continued)
Using posns Write a function right-of-100? which takes in a posn and tells whether its x coordinate is greater than 100 Work this out together
Creating posns Write a function diagonal-posn which takes in a number and produces a posn whose x and y coordinates are both that number Work this out together
Exercises on posns Write a function above-main-diagonal? which takes in a posn and tells whether it is above the diagonal line "x=y" (note that positive x is to the right, and positive y is down, as usual in computer graphics) Write a function posn=? which takes in two posns and tells whether they have the same x coordinate and the same y coordinate Write a function swap-x-y which takes in a posn and returns a posn whose x coordinate is the y coordinate of the given posn, and vice versa.
Optional exercises on posns Write a function distance which takes in two posns and returns their Euclidean distance, which is given by the formula sqrt((x1-x2)^2 + (y1-y2)^2) Write a function scale-posn which takes in a posn and a number and produces a posn by multiplying each coordinate of the given posn by the number Write a function add-posns which takes in two posns and produces a posn whose x coordinate is the sum of their x coordinates, and likewise for the y coordinates
Animations with posn models Write an animation of a picture that moves up, down, left, and right in response to the corresponding arrow keys
Model & handlers • Model is a posn representing center of picture • We'll need a redraw handler; calendar-at-posn : posn -> imageand a key handler; handle-key : posn key -> posn
Redraw handler ; calendar-at-posn : posn -> image (check-expect (calendar-at-posn (make-posn 27 104)) (place-image calendar 27 104 BACKGROUND)) (check-expect (calendar-at-posn (make-posn 215 6)) (place-image calendar 215 6 BACKGROUND)) (define (calendar-at-posn where); where posn; (posn-x where) number; (posn-y where) number(place-image calendar (posn-x where) (posn-y where) BACKGROUND))
Key handler: contract & examples ; handle-key : posn key -> posn (check-expect (handle-key (make-posn 12 47) #\v)(make-posn 12 47)) (check-expect (handle-key (make-posn 12 47) 'up)(make-posn 12 46)) (check-expect (handle-key (make-posn 12 47) 'down)(make-posn 12 48)) (check-expect (handle-key (make-posn 12 47) 'left)(make-posn 11 47)) (check-expect (handle-key (make-posn 12 47) 'right)(make-posn 13 47)) (check-expect (handle-key (make-posn 12 47) ‘home)(make-posn 12 47))
Key handler: skeleton & inventory ; handle-key : posn key -> posn (define (handle-key old-place key) (cond [(key=? key 'left) …] [(key=? key 'right) …] [(key=? key 'up) …] [(key=? key 'down) …] [else old-place]))
Key handler: skeleton & inventory ; handle-key : posn key -> posn (define (handle-key old-place key) (cond [(key=? key 'left) (add-posns old-place (make-posn -1 0))] [(key=? key 'right) (add-posns old-place (make-posn 1 0))] [(key=? key 'up) (add-posns old-place (make-posn 0 -1))] [(key=? key 'down) (add-posns old-place (make-posn 0 1))] [else old-place]))
Or more briefly… ; handle-key : posn char-or-symbol -> posn (define (handle-key old-place key)(add-posns old-place (cond [(symbol=? key 'left) (make-posn -1 0))] [(symbol=? key 'right) (make-posn 1 0)) [(symbol=? key 'up) (make-posn 0 -1)) [(symbol=? key 'down) (make-posn 0 1)) [else (make-posn 0 0))))
Running the animation (define WIDTH 300) (define HEIGHT 300) (define BACKGROUND (rectangle WIDTH HEIGHT "solid" "white")) (run-animation WIDTH HEIGHT(make-posn (/ WIDTH 2) (/ HEIGHT 2))1(on-redraw calendar-at-posn)(on-key handle-key))
Exercises • Write an animation of a picture that, every second, teleports to a random location within the window, but ignores key & mouse events • Write an animation of a picture that moves randomly up, down, left, or right by a pixel each 0.1 second