This lab may look long, but most of the problems should be short.
Summary: In this laboratory, you will explore procedures that have side effects, particularly procedures that generate textual output or read input. Along the way, you should reflect on the differences between the original “just compute a result” model you've mostly used in Scheme, and this new model.
a. If you haven't already, make a copy of io-lab.rkt, which contains
the code from the readings as well as some additional code.
b. Review the file to see what has been added. Make sure that you understand the purpose of the new procedures.
Predict the order in which operations are done in each of the following cases. After you've made each prediction, check your answer experimentally. (It's important to make the prediction first so that you think about order of evaluation.)
a. (add (multiply 1 2) (multiply 3 4))
b. (multiply (add 1 2) (add 3 4))
c. (divide (add 1 2) (add 3 4))
d. (add (multiply 1 (multiply 2 3)) (multiply 4 5))
e. (add (multiply 1 2) (multiply 3 (multiply 4 5)))
a. Look at the code for
and irgb-redder_*. Explain in your
own words what each procedure does.
irgb-lighter_*
b. What output do you expect for the following expression?
>(irgb-redder_* (irgb 220 0 150))
c. Check your answer experimentally.
d. What output do you expect for the following expression?
>(irgb-lighter_* (irgb-redder_* (irgb 220 0 150)))
e. Check your answer experimentally.
a. Look at the code for and
yield. Explain why we need
irgb-yield in addition to
irgb-yield.
yield
b. Rewrite to use
irgb-redder_* instead of
yield.
irgb-yield
c. Rerun the example from above.
>(irgb-redder_* (irgb 200 0 150))
d. Restore the call to in
irgb-yield.
irgb-redder_*
e. Given this additional information, revisit your answer to part a of this exercise.
As you may have noted, we're using the _* suffix to indicate
that we have an “annotated” version of a procedure, one
that tells us what we're doing.
a. Write your own procedure
using irgb-darker_* as a pattern.
irgb-lighter_*
b. Write your own
procedure.
irgb-average_*
Here's a sample call to .
irgb-average_*
>(irgb-average_* (color->irgb "red") (color->irgb "green"))Averaging 255/0/0 and 0/128/0 yields 127/63/08339200
Sometimes it's helpful to see the construction of a new color step by step. In a recent laboratory, we had to write a procedure to swap the red and blue components of a color. Here's how we might have written that procedure.
(define irgb-swap-rb
(lambda (color)
(irgb (irgb-blue color)
(irgb-green color)
(irgb-red color))))
What happens in this procedure? Let's use annotated versions of the various procedures to figure out just what's happening.
a. Add the following procedure to your definitions pane. (This procedure is just the one above, but with the annotated versions of the various procedures it's calling.)
(define irgb-swap-rb
(lambda (color)
(irgb_* (irgb-blue_* color)
(irgb-green_* color)
(irgb-red_* color))))
b. Predict the output you will get when you enter the following in the interactions pane.
>(irgb-swap-rb (irgb 200 50 100))
c. Check your answer experimentally.
Consider the following procedure definition.
>(define fun6 (compose irgb-darker_* irgb-lighter_*))
a. What output do you expect for the following expressions?
>(fun6 (irgb 50 100 150))>(fun6 (irgb 0 0 0))>(fun6 (irgb 255 255 255))>(fun6 (irgb 300 300 300))
b. Check your answer experimentally.
Consider the following procedure definitions.
>(define fun7a (section irgb-average_* <> (irgb 100 100 100)))>(define fun7b (section irgb-average_* (irgb 200 0 200) <>))>(define fun7c (compose fun7a fun7b))>(define fun7d (compose fun7b fun7a))
a. What output do you expect for each of the following expressions? (You need not give exact numbers; just indicate what order you things to be averaged.)
>(fun7a (irgb 0 100 200))>(fun7b (irgb 0 100 200))>(fun7c (irgb 0 100 200))>(fun7d (irgb 0 100 200))
b. Check your answers experimentally.
While the procedure may seem
straightforward, it has some subtleties that may take a bit of exploration
to understand.
read
a. Add the following procedure to your definitions pane.
(define get-number
(lambda ()
(display "Please enter a number: ")
(read)))
b. What do you think will happen when you enter the following expression?
(Assume that you type 5 in response to the prompt.)
>(get-number)
c. Check your answer experimentally.
d. What do you think will happen when you enter the following expression?
(Assume that you type 5 10 in response to the prompt.)
>(get-number)
e. Check your answer experimentally.
f. What do you expect to happen if you call
one more time?
(Assume that you answer (get-number)5 in response to the prompt.)
g. Check your answer experimentally.
h. What, if anything, did you learn from this exercise?
As we noted in the reading, one of the complications of operations with side effects is that the order in which we do those operations can have significant impact. Let's check a particular example.
a. Add yet another subtraction procedure to your definitions pane.
(define sub
(lambda (x y)
(- x y)))
b. What result do you expect to get from the following expression?
Assume that you answer 5 and then 10 when
prompted for numbers.
>(sub (get-number) (get-number))
c. Check your answer experimentally.
What do you expect to happen if you enter 5 10 in response
to the first prompt?
d. Check your answer experimentally.
a. Here are the two programs from the reading.
#lang racket (display "Please enter your name: ") (define name (read-line)) (display "Hello, ") (display name) (newline)
#lang racket (display "Please enter a number: ") (define val (read)) (display val) (display " cubed is ") (display (* val val val)) (newline)
a. Save the first as /home/username/Desktop/hello.rkt.
b. Save the second as /home/username/Desktop/cube.rkt.
c. Open a terminal window and type the following instruction (without the dollar-sign prompt).
$cd /home/username/Desktop
d. Type the following instruction and observe what happens. (Once again, don't type the dollar-sign prompt.)
$racket hello.rkt
e. Type the following instruction and observe what happens. (We think you know what belongs in this parenthetical remark.)
$racket cube.rkt
Consider the following program.
#lang racket (require gigls/unsafe) (display "Input image: ") (image-show (image-variant (image-load (read-line)) irgb-complement))
a. What do you expect to happen when you run this program in DrRacket?
(You can type the file name
/home/rebelsky/Desktop/kitten.jpg.)
b. Check your answer experimentally.
c. Save the file on your desktop and run it from the terminal.
a. Save the following program as
/home/username/Desktop/invert.rkt.
#lang racket (require gigls/unsafe) (display "Input image: ") (define infile (read-line)) (display "Output image: ") (define outfile (read-line)) (image-save (image-variant (image-load infile) irgb-complement) outfile)
b. Predict what this program does.
c. Check your answer experimentally.
If you find that you have extra time, you might want to consider doing the extra problems, which emphasize algorithms and programming, or the explorations, which are more open ended.
Right now, we get a lot of output from the annotated arithmetical procedures. For example,
>(add 2 4)add 2 and 4yields 6
Rewrite the procedures so that we get much more concise, one-liner, output in normal mathematical form. For example,
>(add 2 4)2 + 4 = 6
Write a program that prompts the user for the red, green, and blue components of a color, and also for an image. Your program should build a color from the three numbers, load the image, and then make a new image by averaging every color in the image with that newly built color.
$racket extra2.rktWhat is the red component of your favorite color?200What is the green component of your favorite color?50What is the blue component of your favorite color?240Please enter the full path to an image:/home/rebelsky/Desktop/kitten.jpgThanks! In a minute, you'll see a new version of that image.
Using the input and output techniques we've started to explore, write a simple Mad Libs game. If you've never played Mad Libs, it involves taking a fixed set of text and prompting the user for certain parts of speech that get filled in. Here's a fairly lame example.
Give me some words and I'll tell you a story.Animal:HeffalumpAnother Animal:BandersnatchCity:GrinnellColor:blueMonth:MayAdjective:frumiousExclamation:Wicked Neat!-ing form of verb:excavatingverb:programHere's your story ...One day in May, Winnie the Heffalump was excavating through the wilds of Grinnell. Winnie thought "The month of May is so blue. I wish I could program." Winnie felt very frumious. As Winnie continued excavating, Grinnell's famous Bandersnatch appeared. "Wicked Neat!" thought Winnie.
As you might guess, the code for this is fairly straightforward.
#lang racket (display "Give me some words and I'll tell you a story.") (newline) (display "Animal: ") (define animal (read-line)) ... (display "One day in ") (display month) (display ", Winnie the ") (display animal) ...