;===== ; examples for Week 3 Lecture 2 - 2025-09-11 ; Cleaned up after class! ; last modified: 2025-09-11 (require 2htdp/image) ;===== ; another testing function: check-within ;===== ; * when testing functions involving fractional numbers, ; if a check-expect fails, you can see if check-within ; helps; ; * (to pass, check-expect expects its first two arguments ; to have EXACTLY the same value; but fractional numbers ; are sometimes hard to match EXACTLY when they have many ; less-significant digits, especially when they are not ; all displayed...) ; ; * check-within still expects the expression to test ; and the expected value, ; BUT it also expects a 3rd argument, the margin of error ;----- ; UNCOMMENT this check-expect to see that it fails -- ; (/ 1 3) and .333333333 are not EXACTLY the same value ; ;(check-expect (/ 1 3) ; .333333333 ; ) ;----- ; this check-within passes, however, ; because the values of (/ 1 3) and .33333333 are, ; while not exact, still within .001 from each other (check-within (/ 1 3) .33333333 .001) ;===== ; reminder: scene type ;===== ; from: 2htdp/image !!!!! (corrected after class) ; ; a specialized subtype of the image type ;----- ; 2htdp/universe provides these two very-basic ; scene operations: ;----- ; signature: empty-scene: number number -> scene ; purpose: expects the desired width and height of a scene ; in pixels, and returns a scene of that width and height (empty-scene 200 100) ;----- ; signature: place-image: image number number scene -> scene ; purpose: expects an image, the desired x and y coordinates, ; and a scene, and returns a new scene with the image ; centered at that (x, y) coordinate (and trimmed to fit ; the scene if necessary) ; (but (0, 0) is the top-left...!) ; larger x values are further RIGHT, ; larger y values are further DOWN...!!!!!) ;----- ; that is, here is a scene's coordinate system: ; ; (0,0) 1 2 3 x ; -----|----|----|--> ; | ; | ; 1 - ; | ; | ; 2 - ; | ; | ; 3 - ; | ; y v ;----- ; so, this expression results in a scene of a 30-pixel-radius ; purple circle centered at ; 50 pixels from the left, ; 100 pixels down, ; in a scene that's 200 pixels wide, 200 pixels high (place-image (circle 30 "solid" "purple") 50 100 (empty-scene 200 200)) ;---- ; and, this results in a scene with a 35-pixels-between-its-points ; pink star centered at 100 pixels from the left, ; 150 pixels down, and a 30-pixel-radius purple circle ; centered at 50 pixels from the left, 100 pixels down, ; in a scene that's 200 pixels wide, 200 pixels high (place-image (star 35 "solid" "pink") 100 150 (place-image (circle 30 "solid" "purple") 50 100 (empty-scene 200 200))) ;===== ; For some animations I would like to make, ; I am going to have a number of scene instances of the ; the same size and width ; SO: I am making some named constants to make this ; more readable (and more maintainable) (define WIDTH 400) (define HEIGHT 200) WIDTH HEIGHT (define BACKDROP (empty-scene WIDTH HEIGHT)) BACKDROP ;===== ; I would like a function that expects a star size ; and returns a scene of a cyan star of that size ; in its center ;----- ; I want to reuse cyan-star from Week 2 Lecture 2: ; (NEED to copy its function header and body to do so -- ; and any other named constants or functions IT uses -- ; and CLASS STYLE is also to copy over its signature ; and purpose comments, and its tests/check- expressions ;===== ; slightly-edited FROM WEEK 2 LECTURE 2 ;===== ;----- ; signature: cyan-star: number -> image ; purpose: expects the distance between a 5-pointed ; star's points, and returns a solid cyan star image ; of that size (check-expect (cyan-star 30) (star 30 "solid" "cyan")) (check-expect (cyan-star 50) (star 50 "solid" "cyan")) (define (cyan-star star-size) (star star-size "solid" "cyan") ) ;===== (END of part copied over from Week 2 Lecture 2) ;----- ; continuing, now, with the design recipe steps for ; this scene function: ;===== ; signature: cyan-star-scene: number -> scene ; purpose: expects a desired star size (distance in pixels ; between its points) and returns a scene of size ; WIDTH by HEIGHT with a cyan star of that size centered ; within it (check-expect (cyan-star-scene 50) (place-image (cyan-star 50) (/ WIDTH 2) (/ HEIGHT 2) BACKDROP)) (check-expect (cyan-star-scene 150) (place-image (cyan-star 150) (/ WIDTH 2) (/ HEIGHT 2) BACKDROP)) (define (cyan-star-scene star-size) (place-image (cyan-star star-size) (/ WIDTH 2) (/ HEIGHT 2) BACKDROP) ) (cyan-star-scene 50) (cyan-star-scene 150) ;===== ; starting intro to function: big-bang ;===== ;===== ; function big-bang is defined in the module ; 2htdp/universe, so to use it, you need: (require 2htdp/universe) ;----- ; big-bang is a function with numerous side-effects! ;----- ; big-bang expects at least 2 arguments; ; the first is the initial value of a new "world" ; (and the type of that value becomes the type ; of the new world) ; the remainder are event-handler clauses, ; special compound expressions ; that start with the name of an event ; and are followed with the NAME of a function ; to be called when that event happens (an event-handler ; function) ; (and a few have additional optional arguments) ; ; and, big-bang returns the value of its world when it is ended ;----- ; when you call big-bang, it starts a ticker ticking, ; (about 28 times per second, although you can specify ; a different speed) ; * and each time its ticker ticks, it wants to ; create a scene and display it in a pop-up World ; window ;----- ; when does a running big-bang expression end? ; ; * when you CLOSE its World window (clicking on its ; top-left corner) ; ; * when you click DrRacket's Stop button in its ; top-right corner (but this ends your current Racket ; program, also) ; * (and the World window remains open until you close it, ; even though big-bang is no longer running) ; ; * there is also a clause you can add to specify when it ; should stop (see below) ; ; * and, a run-time error will kill it, too! (and the World window ; remains open in this case, also...) ;----- ; GOING ON: the event you MUST handle is when big-bang wants to ; depict its world, to draw a scene based on its current ; world value; ; ; to-draw ; ; (big-bang initial-world-expr ; (to-draw desired-funct) ; ...) ; ; when the to-draw event occurs (for example, after each ticker tick), ; big-bang calls the function you give to-draw as its argument ; with the current world value as *its* argument, ; and it displays the resulting scene in a pop-up window "should see a pop-up window with an unchanging cyan star in" " the center;" "CLOSE that window to continue!" (big-bang 15 (to-draw cyan-star-scene)) ;----- ; as mentioned, each time you call function big-bang, ; big-bang starts up a ticker that ticks about ; 28 times per second; ; each time the ticker ticks, big-bang calls to-draw's function ; to depict the current world value's scene; ; BUT -- IF you also have an on-tick clause -- ; at the event of each ticker tick, ; big-bang calls the on-tick clause's function ; with the current world value, ; and what that function returns becomes the *new* world value ;===== ; FUN FACT: Racket has a function add1, that does what you ; would probably guess it does: adds 1 to something! ;----- ; signature: add1: number -> number ; purpose: expects any number, and returns the result ; of adding 1 to it (add1 56) ;===== ; SO, if big-bang's world type - the type of its first argument - is number, ; I can use add1 as on-tick's argument, ; and each time big-bang's ticker ticks, ; big-bang will call add1 with the current world value ; to result in a new world value: "should see a pop-up window with a GROWING cyan star in" " the center;" "CLOSE that window to continue!" (big-bang 30 (to-draw cyan-star-scene) (on-tick add1)) ;===== ; FUN FACT: Racket has a function sub1, also, that ; subtracts 1 from something! ;----- ; signature: sub1: number -> number ; purpose: expects any number, and returns the result ; of subtracting 1 from it (sub1 56) ;---- ; SO -- see what happens when you use sub1 as the event-handler ; function for the event on-tick: "should see a pop-up window with a SHRINKING cyan star in" " the center;" "CLOSE that window before world value gets to 0 to continue," " otherwise big-bang will be stopped by the error that happens" " when cyan-star-scene calls cyan-star and cyan-star calls" " function star with a non-zero size!" " " " (if you try out the error, you'll need to close the world pop-up" " window or it just sticks around...)" (big-bang 200 (to-draw cyan-star-scene) (on-tick sub1)) ;----- ; BUT another optional event-handler clause big-bang has ; is stop-when; ; stop-when expects a function that expects the current world ; value type and returns a boolean, ; ; and each time big-bang's ticker ticks, big-bang calls ; stop-when's function with the current world, ; and if that function returns #true, big-bang ENDS ; ; (get it? "stop when this function is true"...) ; ; (but it does leave the World window open, oddly enough!) "should see a pop-up window with a SHRINKING teal star in" " the center;" " it will gracefully END when big-bang's world value reaches 0," " BUT you will need to close the world pop-up" " window or it just sticks around...)" (big-bang 150 (to-draw cyan-star-scene) (on-tick sub1) (stop-when zero?)) ;----- ; playing around: ; ; Racket has a random function that expects a ; desired limit (max) and returns an integer ; >= 0 and < than that maximum (random 300) ; UNCOMMENT the following to see how our experiment trying ; random as on-tick's event handler function is less than ; successful...! ; ;"this attempt to use random as the on-tick event handler" ;" function ends quickly with an error" ;" because the world's value will quickly approach and reach 0" ;" " ;"(you'll need to close the world pop-up" ;" window or it just sticks around...)" ; ;(big-bang 200 ; (to-draw cyan-star-scene) ; (on-tick random))