Modeling a Ball on a Table

Let's consider the simple-looking problem of modeling the moves of a ball across a table. Assume the ball rolls at a constant speed until drops. We can model the table with a canvas of some fixed width and height. The ball is a disk that moves across the canvas, which we express with drawing the disk, waiting, and clearing it, until it is out of bounds.
<#32788#>;; TeachPack: draw.ss <#32788#>
<#32789#>(define-struct<#32789#> <#32790#>ball<#32790#> <#32791#>(x<#32791#> <#32792#>y<#32792#> <#32793#>delta-x<#32793#> <#32794#>delta-y))<#32794#> 
<#71450#>;; A <#66135#><#32795#>ball<#32795#><#66135#> is a structure: <#71450#> 
<#32796#>;; (make-ball number number number number)<#32796#> 
<#71451#>;; <#66136#><#32797#>draw-and-clear<#32797#> <#32798#>:<#32798#> <#32799#>a-ball<#32799#> <#32800#><#32800#><#32801#>-;SPMgt;<#32801#><#32802#><#32802#> <#32803#>true<#32803#><#66136#><#71451#> 
<#32804#>;; draw, sleep, clear a disk from the canvas <#32804#> 
<#32805#>;; structural design, Scheme knowledge<#32805#> 
<#32806#>(d<#32806#><#32807#>efine<#32807#> <#32808#>(draw-and-clear<#32808#> <#32809#>a-ball)<#32809#> 
  <#32810#>(<#32810#><#32811#>and<#32811#> 
   <#32812#>(draw-solid-disk<#32812#> <#32813#>(make-posn<#32813#> <#32814#>(ball-x<#32814#> <#32815#>a-ball)<#32815#> <#32816#>(ball-y<#32816#> <#32817#>a-ball))<#32817#> <#32818#>5<#32818#> <#32819#>RED)<#32819#> 
   <#32820#>(sleep-for-a-while<#32820#> <#32821#>DELAY)<#32821#> 
   <#32822#>(clear-solid-disk<#32822#> <#32823#>(make-posn<#32823#> <#32824#>(ball-x<#32824#> <#32825#>a-ball)<#32825#> <#32826#>(ball-y<#32826#> <#32827#>a-ball))<#32827#> <#32828#>5<#32828#> <#32829#>RED)))<#32829#> 
<#71452#>;; <#66137#><#32830#>move-ball<#32830#> <#32831#>:<#32831#> <#32832#>ball<#32832#> <#32833#><#32833#><#32834#>-;SPMgt;<#32834#><#32835#><#32835#> <#32836#>ball<#32836#><#66137#><#71452#> 
<#71453#>;; to create a new ball, modeling a move by <#66138#><#32837#>a-ball<#32837#><#66138#><#71453#> 
<#32838#>;; structural design, physics knowledge<#32838#> 
<#32839#>(d<#32839#><#32840#>efine<#32840#> <#32841#>(move-ball<#32841#> <#32842#>a-ball)<#32842#> 
  <#32843#>(make-ball<#32843#> <#32844#>(+<#32844#> <#32845#>(ball-x<#32845#> <#32846#>a-ball)<#32846#> <#32847#>(ball-delta-x<#32847#> <#32848#>a-ball))<#32848#> 
             <#32849#>(+<#32849#> <#32850#>(ball-y<#32850#> <#32851#>a-ball)<#32851#> <#32852#>(ball-delta-y<#32852#> <#32853#>a-ball))<#32853#> 
             <#32854#>(ball-delta-x<#32854#> <#32855#>a-ball)<#32855#> 
             <#32856#>(ball-delta-y<#32856#> <#32857#>a-ball)))<#32857#> 
<#32858#>;; Dimension of canvas <#32858#> 
<#32859#>(define<#32859#> <#32860#>WIDTH<#32860#> <#32861#>100)<#32861#> 
<#32862#>(define<#32862#> <#32863#>HEIGHT<#32863#> <#32864#>100)<#32864#> 
<#32865#>(define<#32865#> <#32866#>DELAY<#32866#> <#32867#>.1)<#32867#> 
<#66139#>Figure: Auxiliaries for <#32871#>move-until-out<#32871#><#66139#>
Figure~#figmoveout#32873> collects the function, structure, data, and variable definitions that model the ball:
  1. A ball is a structure with four fields, which are the current position and the velocity in each direction. That is, the first two numbers in a <#66140#><#32875#>ball<#32875#><#66140#> structure are the current position on the canvas, and the next two numbers describe how far the ball moves in the two directiones per step.
  2. The function <#66141#><#32876#>move-ball<#32876#><#66141#> models the physical movement of the ball. It consumes a ball and creates a new one, modeling one step.
  3. The function <#66142#><#32877#>draw-and-clear<#32877#><#66142#> draws the ball at its current position, then waits for a short time, and clears it again.
The variable definitions specify the dimensions of the canvas and the delay time. To move the ball a few times we can write
<#32883#>(define<#32883#> <#32884#>the-ball<#32884#> <#32885#>(make-ball<#32885#> <#32886#>10<#32886#> <#32887#>20<#32887#> <#32888#>-5<#32888#> <#32889#>+17))<#32889#>
<#32890#>(<#32890#><#32891#>and<#32891#> 
 <#32892#>(draw-and-clear<#32892#> <#32893#>the-ball)<#32893#> 
 <#32894#>(a<#32894#><#32895#>nd<#32895#> 
   <#32896#>(draw-and-clear<#32896#> <#32897#>(move-ball<#32897#> <#32898#>the-ball))<#32898#> 
   <#32899#>...))<#32899#> 
though this gets tedious after a while. We should instead develop a function that moves the ball until it is out of bounds. The easy part is to define <#66143#><#32903#>out-of-bounds?<#32903#><#66143#>, a function that determines whether a given ball is still visible on the canvas:
<#71454#>;; <#66144#><#32908#>out-of-bounds?<#32908#> <#32909#>:<#32909#> <#32910#>a-ball<#32910#> <#32911#><#32911#><#32912#>-;SPMgt;<#32912#><#32913#><#32913#> <#32914#>boolean<#32914#><#66144#><#71454#>
<#71455#>;; to determine whether <#66145#><#32915#>a-ball<#32915#><#66145#> is outside of the bounds<#71455#> 
<#32916#>;; domain knowledge, geometry<#32916#> 
<#32917#>(d<#32917#><#32918#>efine<#32918#> <#32919#>(out-of-bounds?<#32919#> <#32920#>a-ball)<#32920#> 
  <#32921#>(<#32921#><#32922#>not<#32922#> 
   <#32923#>(a<#32923#><#32924#>nd<#32924#> 
     <#32925#>(;SPMlt;=<#32925#> <#32926#>0<#32926#> <#32927#>(ball-x<#32927#> <#32928#>a-ball)<#32928#> <#32929#>WIDTH)<#32929#> 
     <#32930#>(;SPMlt;=<#32930#> <#32931#>0<#32931#> <#32932#>(ball-y<#32932#> <#32933#>a-ball)<#32933#> <#32934#>HEIGHT))))<#32934#> 
We have defined numerous functions like <#66146#><#32938#>out-of-bounds?<#32938#><#66146#> in the first few sections of the book. In contrast, writing a function that draws the ball on the canvas until it is out of bounds belongs to a group of programs that we haven't encountered thusfar. Let's start with the basics of the function:
<#71456#>;; <#66147#><#32943#>move-until-out<#32943#> <#32944#>:<#32944#> <#32945#>a-ball<#32945#> <#32946#><#32946#><#32947#>-;SPMgt;<#32947#><#32948#><#32948#> <#32949#>true<#32949#><#66147#><#71456#>
<#32950#>;; to model the movement of a ball until it goes out of bounds<#32950#> 
<#32951#>(define<#32951#> <#32952#>(move-until-out<#32952#> <#32953#>a-ball)<#32953#> <#32954#>...)<#32954#> 
Because the function consumes a ball and draws its movement on a canvas, it produces <#66148#><#32958#>true<#32958#><#66148#> like all other functions that draw into a canvas. Designing it with the recipe for structures makes no sense, however. After all, it is already clear how to <#66149#><#32959#>draw-and-clear<#32959#><#66149#> the ball and how to move it, too. What is needed instead, is a case distinction that checks whether the ball is out of bounds or not. Let us refine the function header with an appropriate <#66150#><#32960#>cond<#32960#>-expression<#66150#>:
<#32965#>(d<#32965#><#32966#>efine<#32966#> <#32967#>(move-until-out<#32967#> <#32968#>a-ball)<#32968#>
  <#32969#>(c<#32969#><#32970#>ond<#32970#> 
    <#32971#>[<#32971#><#32972#>(out-of-bounds?<#32972#> <#32973#>a-ball)<#32973#> <#32974#>...]<#32974#> 
    <#32975#>[<#32975#><#32976#>else<#32976#> <#32977#>...]<#32977#><#32978#>))<#32978#> 
We have already defined the function <#66151#><#32982#>out-of-bounds?<#32982#><#66151#> because it was clear from the problem description that ``being out of bounds'' was a separate concept. If the ball consumed by <#66152#><#32983#>move-until-out<#32983#><#66152#> is outside of the canvas's boundaries, the function can produce <#66153#><#32984#>true<#32984#><#66153#>, following the contract. If the ball is still inside the boundaries, two things must happen. First, the ball must be drawn and cleared from the canvas. Second, the ball must be moved and then we must do things all over again. This implies that after moving the ball, we apply <#66154#><#32985#>move-until-out<#32985#><#66154#> again, which means the function is recursive:
<#71457#>;; <#66155#><#32990#>move-until-out<#32990#> <#32991#>:<#32991#> <#32992#>a-ball<#32992#> <#32993#><#32993#><#32994#>-;SPMgt;<#32994#><#32995#><#32995#> <#32996#>true<#32996#><#66155#><#71457#>
<#32997#>;; to model the movement of a ball until it goes out of bounds<#32997#> 
<#32998#>(d<#32998#><#32999#>efine<#32999#> <#33000#>(move-until-out<#33000#> <#33001#>a-ball)<#33001#> 
  <#33002#>(c<#33002#><#33003#>ond<#33003#> 
    <#33004#>[<#33004#><#33005#>(out-of-bounds?<#33005#> <#33006#>a-ball)<#33006#> <#33007#>true]<#33007#> 
    <#33008#>[<#33008#><#33009#>else<#33009#> <#33010#>(and<#33010#> <#33011#>(draw-and-clear<#33011#> <#33012#>a-ball)<#33012#> 
               <#33013#>(move-until-out<#33013#> <#33014#>(move-ball<#33014#> <#33015#>a-ball)))]<#33015#><#33016#>))<#33016#> 
Both <#66156#><#33020#>(draw-and-clear<#33020#>\ <#33021#>a-ball)<#33021#><#66156#> and <#66157#><#33022#>(move-until-out<#33022#><#33023#> <#33023#><#33024#>(move-ball<#33024#>\ <#33025#>a-ball))<#33025#><#66157#> produce true, and both expressions must be evaluated. So we combine them with an <#66158#><#33026#>and<#33026#>-expression<#66158#>. We can now test the function as follows:
<#33031#>(start<#33031#> <#33032#>WIDTH<#33032#> <#33033#>HEIGHT)<#33033#>
<#33034#>(move-until-out<#33034#> <#33035#>(make-ball<#33035#> <#33036#>10<#33036#> <#33037#>20<#33037#> <#33038#>-5<#33038#> <#33039#>+17))<#33039#> 
<#33040#>(stop)<#33040#> 
This creates a canvas of proper size and a ball that moves left and down. A close look at the function definition reveals two peculiarities. First, although the function is recursive, its body consists of a <#66159#><#33044#>cond<#33044#>-expression<#66159#> whose conditions have nothing to do with the input data. Second, the recursive application in the body does not consume a part of the input. Instead, <#66160#><#33045#>move-until-out<#33045#><#66160#> generates an entirely new and different <#66161#><#33046#>ball<#33046#><#66161#> structure, which represents the original ball after one step, and uses it for the recursion. Clearly, none of our design recipes could possibly produce such a definition. We have encountered a new way of programming.
<#33049#>Exercise 25.1.1<#33049#> What happens if we place the following three expressions
<#33055#>(start<#33055#> <#33056#>WIDTH<#33056#> <#33057#>HEIGHT)<#33057#>
<#33058#>(move-until-out<#33058#> <#33059#>(make-ball<#33059#> <#33060#>10<#33060#> <#33061#>20<#33061#> <#33062#>0<#33062#> <#33063#>0))<#33063#> 
<#33064#>(stop)<#33064#> 
at the bottom of the <#33068#>Definitions<#33068#> window and click <#33069#>Execute<#33069#>? Does the second expression ever produce a value so that the third expression is evaluated and the canvas disappears? Could this happen with any of the functions designed according to our old recipes?~ external Solution<#66162#><#66162#> <#33075#>Exercise 25.1.2<#33075#> Develop <#66163#><#33077#>move-balls<#33077#><#66163#>. The function consumes a list of balls and moves each one until all of them have moved out of bounds. <#33078#>Hint:<#33078#> It is best to write this function using <#66164#><#33079#>filter<#33079#><#66164#>, <#66165#><#33080#>andmap<#33080#><#66165#>, and similar abstract functions from part~#partabstract#33081>. external Solution<#66166#><#66166#>