button is located in the top right of your Dr. Scheme window. In
order to use the Step feature, however, you must change the
Scheme language you are using from Graphical
(MrEd, includes MzScheme) to Intermediate
Student with lambda. To do this, select Choose
Language... from the Language menu. In the new window,
first select How to Design Programs under the Teaching Languages section, then select
Intermediate Student with lambda and press OK. In order
for the change to take effect, press the
button. In the Interactions window you should see
"Language: Intermediate Student with
lambda.". When you are done with this part of the lab, we will
change the language back to Graphical (MrEd,
includes MzScheme). You should be able to refer back to these
directions to do so.
Let's do a simple example so that you can do the more complex examples on your own.
(+ 3 (/ (- 13 2) 4))
button. The Stepper window will
appear which contains the following:
as
.
button in the Stepper window will progress the evaluation one more step:

yields the final evaluation:

(define fact
(lambda (n)
(if (= n 0)
1
(* n (fact (- n 1))))))
In the Interactions window, try the following to see that the fact function implements factorial.
(fact 3) ; => 3 * 2 * 1 = 6 (fact 5) ; => 5 * 4 * 3 * 2 * 1 = 120Now, put (fact 4) in the Definition window and step through the evaluation. Make sure you understand what is happening and call me over if you have questions.
As the first line in your Definitions window, add the following to allow function tracing:
(require (lib "trace.ss"))Next, add the following two lines to the end of the Definitions window:
(trace fact) (fact 4)After you
the program, you will see something like following (I have added the comments for your benefit):
|(fact 4) ;trace showing that fact is invoked with arg 4 | (fact 3) ;trace showing that fact is invoked with arg 3 from (fact 4) | |(fact 2) ;trace showing that fact is invoked with arg 2 from (fact 3) | | (fact 1) ;trace showing that fact is invoked with arg 1 from (fact 2) | | |(fact 0) ;trace showing that fact is invoked with arg 0 from (fact 1) | | |1 ;trace showing value returned from (fact 0) is 1 | | 1 ;trace showing value returned from (fact 1) is 1 | |2 ;trace showing value returned from (fact 2) is 2 | 6 ;trace showing value returned from (fact 3) is 6 |24 ;trace showing value returned from (fact 4) is 24You may be interested to know that you can trace any function, both those that you write, as well as primitive functions. Change the (trace fact) line you wrote in the Definitions window to (trace fact * -). This will now trace the fact function you wrote, as well as the primitive functions * and +. Now, re-run your program.
The output can get pretty messy with all of those functions traced!
Though you don't need it here, it may be useful to remember that you can tell Scheme to stop tracing functions using untrace, e.g. (untrace * -)
Note: You cannot use the
function in the full version of Scheme (Graphical
(MrEd, includes MzScheme)), and you cannot trace
functions in the trimmed-down version of Scheme (Intermediate Student with lambda).
Here are some things to note as we get started:
(require (lib "graphics.ss" "graphics"))
(open-graphics)
(define win1 (open-viewport "cs37" 500 500))
((draw-line win1) (make-posn 100 100) (make-posn 300 400)) ((draw-line win1) (make-posn 10 100) (make-posn 30 40)) ((draw-line win1) (make-posn 10 100) (make-posn 100 100)) ((draw-solid-rectangle win1) (make-posn 20 300) 30 30 (make-rgb 1 0 0))
A couple of more useful commands are (don't type these in - just read them through):
(close-graphics) ; closes all graphics viewports that may be open (close-viewport win1) ; closes the viewport named win1 ((clear-viewport win1)) ; erases the viewport named win1
((draw-line win1) (make-posn 10 100) (make-posn 100 100) (make-rgb 0 0 1))We can write a function called draw-blue-line which takes the starting point (x1, y1) and ending point (x2, y2) as 4 parameters and draws a blue line in the viewport win1:
(define draw-blue-line
(lambda (x1 y1 x2 y2)
((draw-line win1)
(make-posn x1 y1)
(make-posn x2 y2)
(make-rgb 0 0 1))))
Type the above function into the Definitions window and run the
program. In the Interactions window, try drawing a couple of blue
lines using draw-blue-line. Call me over if you need help.
Note: You should always be sure to save your file often. This might be a good time to do so.
Suppose you want to draw two lines of equal length that meet at a right angle and such that the unattached end point of one line is (x1, y1) and the unattached endpoint of the other line is (x2, y2). That is, we want to draw the two legs of an isosceles right triangle whose hypotenuse is the straight line from (x1, y1) to (x2, y2). We can do this by finding the coordinates of the right angle vertex, (xm, ym), and then drawing a line from (x1, y1) to (xm, ym) and another line from (xm, ym) to (x2, y2). There are actually 2 possible vertices (xm, ym) that will work, one on each side of the hypotenuse. Using a little math, one possible set of coordinates are xm=(x1+x2+y1-y2)/2 and ym=(x2+y1+y2-x1)/2. We can write a function to draw these two legs in viewport win1. Notice that in the solution below, we first define the function draw-lines inside the definition of two-legs:
(define two-legs
(lambda (x1 y1 x2 y2)
(define draw-lines ;;;draw-lines from the provided
(lambda (xm ym) ;;;(xm, ym) to (x1, y1) and (x2, y2),
(draw-blue-line x1 y1 xm ym) ;;;forming the right angle
(draw-blue-line xm ym x2 y2)))
(draw-lines ;;;call the draw-lines function with
(/ (- (+ x1 x2 y1) y2) 2) ;;;the computed argument for xm and
(/ (- (+ x2 y1 y2) x1) 2)))) ;;;the computed argument for ym
Add the definition of two-legs to the Definitions window
(then press Run) and the try it out from the Interactions window:
(draw-blue-line 50 50 100 150) ;;;draw the hypotenuse (two-legs 50 50 100 150) ;;;draw the two legsYou should notice that you can draw the two legs without drawing the hypotenuse. Try doing so with a few different sets of coordinates.
Reminder note: Don't forget to save your file often!
We could try and write a new procedure to draw level 2 C-curves, then another for procedure level 3 C-curves... but this lab is all about using recursion. So instead, we will write a function called c-curve which draws a C-curve of level n by following the definition we wrote above:
(define c-curve
(lambda (x1 y1 x2 y2 level)
(define draw-curves
(lambda (xm ym) ;;;draws the lower level curves
(c-curve x1 y1 xm ym (- level 1)) ;;;to the midpoint (xm, ym) from
(c-curve xm ym x2 y2 (- level 1)))) ;;;(x1, y1) and (x2, y2)
(if (= level 0)
(draw-blue-line x1 y1 x2 y2) ;;;level 0 so draw a straight line
(draw-curves ;;;level is greater than 0 so
(/ (- (+ x1 x2 y1) y2) 2) ;;;call draw-curves with the
(/ (- (+ x2 y1 y2) x1) 2))))) ;;;computed midpoint
Add the c-curve function to your Definitions window and press Run (and save it).
Try each of the following in the Interactions window:
(c-curve 250 100 350 300 0) (c-curve 250 100 350 300 1) (c-curve 250 100 350 300 2)
Now add (require (lib "trace.ss")) to the top of the Definitions window and hit Run. (This line can go before or after the require line which included the graphics library.)
Then in interaction window, type:
(trace c-curve draw-blue-line)Now draw a level 0 C-curve and examine the traced output. You should see the value #<void>. For now, you can ignore why this happens, but you should realize they are the return values of c-curve and draw-blue-line.
(c-curve 250 100 350 300 0)
Clear the graphics window and draw a level 1 C-curve, examining the traced output:
((clear-viewport win1)) ;notice there are two parenthesis on each end (c-curve 250 100 350 300 1)
Clear the graphics window and draw a level 2 C-curve, again examining the traced output:
((clear-viewport win1)) (c-curve 250 100 350 300 2)
Make sure you understand the curve drawn and how it relates to the output of the trace. Call me over if you have questions.
Untrace the functions you had traced, clear the viewport, and draw a level 13 C-curve:
(untrace draw-blue-line c-curve) ((clear-viewport win1)) (c-curve 250 100 350 300 13)You can also play with one C-curve on top of another. For example, drawing a level 15 curve on a level 11 curve, or a level 4 curve on a level 3 curve.
That's it for today. If you finished, great.
If you didn't,
finish it up by next class and ask me questions next time if you have them.