Functional Problem Solving (CSC 151 2016S) : EBoards
Primary: [Front Door] [Schedule] - [Academic Honesty] [Disabilities] [Email] - [FAQ] [Teaching & Learning] [Grading] [Taking Notes] [Rubric]
Current: [Assignment] [EBoard] [Lab] [Outline] [Reading]
Sections: [Assignments] [EBoards] [Labs] [Outlines] [Readings] - [Examples] [Handouts]
Reference: [Setup] [Remote] [VM] [Errors] - [Functions A-Z] [Functions By Topic] - [Racket] [Scheme Report (R5RS)] [R6RS] [TSPL4]
Related Courses: [Curtsinger (2016S)] [Davis (2013F)] [Rebelsky (2015F)] [Weinman (2014F)]
Misc: [SamR] [Glimmer Labs] [CS@Grinnell] [Grinnell] - [Issue Tracker (Course)]
Thank you to the students who showed up so that we get a review session that other students can read over later.
Overview
None yet.
Reminders: It's good to ask questions. It's good to look at the exam asap.
Topics
sectionlambdaForm
'll try to gather them all and then answer them.
Can we talk a bit more about section?
sectionis a procedure that makes procedures. One of three mechanisms we currently know (the others arecomposeandlambda).Like
compose,sectionmakes procedures only from existing procedures.We make new procedures by "filling in" one or more parameters of the existing procedure.
A few examples
; Know (expt base power) and computes base*base*base*...base
; power times.
(define square (section expt <> 2))
(define three-to-the (section expt 3 <>))
Note:
sectionis part of the gigls library.You can have more than one "open space"
(define stupid (section - <> 3 <>))
> (define stupid (section - <> 3 <>))
> (stupid 2)
. . stupid: arity mismatch;
the expected number of arguments does not match the given number
expected: 2
given: 1
arguments...:
2
> (stupid 5 2)
0
> ; That's 5 - 3 - 2
(define rg (section irgb <> <> 0))
> (rg 200 100)
13132800
> (irgb->string (rg 200 100))
"200/100/0"
We do not write an open paren before the procedure name in
section(nor incompose, nor inimage-variant, nor in others that we'll see soon).
Are there things we can do with section that we can't do with
lambda, and vice versa?
Anything you can do with
section, you can do with lambda. It's just more text. (Stylistic, rather than preferences.)
(define rg
(lambda (r g)
(irgb r g 0)))
There are many things you can do with lambda that you can't do with
section.
(define pointless
(lambda (x)
(* x (+ x x))))
lambda, unlikesection, is a standard part of Scheme (core to Scheme)We tend to use
lambdaexcept whensectionandcomposemake our code more concise (or more readable).
Consider the following procedure
(define fun
(compose image-show
(section image-variant
(image-load "/home/rebelsky/Desktop/kitten.jpg")
<>)))
Write the first four P's of the six-P style documentation for this procedure.
;;; Procedure:
;;;
;;; Parameters:
;;;
;;; Purpose:
;;;
;;; Produces:
;;;
Consider the following procedures
(define yield
(lambda (val)
(display " yields ")
(display val)
(newline)
val))
(define add
(lambda (x y)
(display x)
(display " plus ")
(display y)
(yield (+ x y))))
(define square
(lambda (x)
(display x)
(display " squared ")
(yield (* x x))))
What output and result should you get for each of the following expressions?
(add 2 3)
(add x y)
(add (square 2) (square 3))
(square (add 2 3))
(add (square 2) (square (square 3)))
Write (irgb-average color1 color2), which averages the red, green, and
blue components of color and color2.
(define irgb-average
(lambda (color1 color2)
....))
Consider the following procedure, which computes the largest of the three components of an integer-encoded RGB color.
(define irgb-max
(lambda (color)
(max (irgb-red color)
(irgb-green color)
(irgb-blue color))))
Write a procedure, irgb-max_*, which takes the same input as irgb-max,
generates the same output as irgb-max, and also prints a short message
describing these input and output. You may use display and yield
in your instructions.
Consider the following two procedures
(define f1
(lambda (color)
(irgb (* (irgb-red color)
(quotient (irgb-red color)
(irgb-max_* color)))
(* (irgb-green color)
(quotient (irgb-green color)
(irgb-max_* color)))
(* (irgb-blue color)
(quotient (irgb-blue color)
(irgb-max_* color))))))
(define f2
(lambda (color)
(f2-helper color (irgb-max_* color))))
(define f2-helper
(lambda (color cmax)
(irgb (* (irgb-red color)
(quotient (irgb-red color) cmax))
(* (irgb-green color)
(quotient (irgb-green color) cmax))
(* (irgb-blue color)
(quotient (irgb-blue color) cmax))
We should get the same return value from f1 and f2. But will we
see the same output (generated by irgb-max_*)? Why or why not?
Taylor and Jordan have decided to write a procedure that makes colors
more like cyan. They call it cyanide. (Don't blame me; it's their
idea.) (cyanide color) should produce a new color in which the red
component decreases by 16 (or to 0, if the component is less than 16),
the blue component increases by 16 (or to 255, if the component is more
than 239), and the green component also increases by 16 (or to 255,
if the component is more than 239).
Without using lambda, write cyanide. You will likely need
to use section and compose.
p.s. Here's the 6P-style documentation.
;;; Procedure:
;;; cyanide
;;; Parameters:
;;; color, an integer-encoded RGB color
;;; Purpose:
;;; Make color look more like "cyan"
;;; Produces:
;;; poisoned, an integer-encoded RGB color
;;; Preconditions:
;;; [No additional]
;;; Postconditions:
;;; (irgb-red poisoned) = (max 0 (- (irgb-red color) 16))
;;; (irgb-green poisoned) = (min 255 (+ (irgb-green color) 16))
;;; (irgb-blue poisoned) = (min 255 (+ (irgb-blue color) 16))
And here's an alternate postcondition
;;; Postconditions:
;;; If (irgb-red color) >= 16
;;; (irgb-red poisoned) = (- (irgb-red color) 16)
;;; If (irgb-red color) < 16
;;; (irgb-red poisoned) = 0
;;; If (irgb-green poisoned) <= 239
;;; (irgb-green poisoned) = (+ (irgb-green color) 16)
;;; If (irgb-green poisoned) > 239
;;; (irgb-green poisoned) = 255
;;; If (irgb-blue poisoned) <= 239
;;; (irgb-blue poisoned) = (+ (irgb-blue color) 16)
;;; If (irgb-blue poisoned) > 239
;;; (irgb-blue poisoned) = 255
; Three tasks: ; Subtract 16 from the red component. ; (section irgb-subtract <> (irgb 32 0 0)) ; Add 16 to the green component. ; (section irgb-add <> (irgb 0 16 0)) ; Add 16 to the blue component. ; (section irgb-add <> (irgb 0 0 16)) (define cyanide (compose (section irgb-subtract <> (irgb 32 0 0)) (section irgb-add <> (irgb 0 16 0)) (section irgb-add <> (irgb 0 0 16))))
(define cyanide (compose (section irgb-subtract <> (irgb 32 0 0)) (section irgb-add <> (irgb 0 16 16))))
(define cyanide
(compose irgb-greener irgb-bluer irgb-darker))
This isn't as good, because a blue component of 5 gets turned into 32 rather than 21.
But life is imperfect.
What does the following procedure do?
(define c (compose (section min 100 <>) (section max 0 <>)))
What does the following procedure do?
(define d (compose (section max 100 <>) (section min 0 <>)))
(section max 0 <>) computes the larger of its parameter and 0.
Positive numbers stay positive. Negative numbers become 0.
(section min 100 <>) computes the smaller of its parameter and 100.
Numbers below 100 stay the same.
Email me questions and I will respond as quickly and in as much detail as I can. rebelsky@grinnell.edu
Enjoy the lovely sunny day.
Why do we have val as the last element of yield?
(define f1
(lambda (x)
1
2
3))
> (f1 7)
3
; Scheme gives you the *last* value computed in a procedure if there
; are a series of computations
(define f2
(lambda (x)
(display x)
(newline)
2
3))
> (f2 7)
7 ; purple to indicate "displayed"
3 ; blue to indicate "returned/computed"
> (+ 1 (f2 7))
7 ; purple to indicate "displayed"
4 ; blue to indicate "returned/computed"
(define f3
(lambda (x)
(display x)
(newline)))
> (f3 7)
7 ; purple to indicate "displayed"
> (+ 1 (f3 7))
; Error! Can't add 1 to #<void>
> (+ 1 (newline))
; Error! Can't add 1 to #<void>
> (+ 1 (display x))
; Error! Can't add 1 to #<void>
(define yield
(lambda (val)
(display " yields ")
(display val)
(newline)
val)) ; Now the calling procedure can use `val`.
; yield is like `f3` but with `val` at the end.
Why do we have the newline?
It means that the next thing we display will be on the next line.
How do we transform colors without using lambda?
Two approaches.
Using compose and existing one-parameter procedures.
E.g., to reduce the red component by 32 ... we know how to increemnt the red component by 32 (
irgb-redder), but that's backwards. What else would help? We know how to "invert" the values in a color (irgb-complement). Theory: Invert, increment by 32, and invert, we've effectively decremented.Solution
(define irgb-less-red (compose irgb-complement irgb-redder irgb-complement))We also have some useful two-parameter procedures.
irgb-addandirgb-subtractmight be useful. (Component-wise addition or subtraction.)
(define irgb-less-red (section irgb-subtract <> (irgb 32 0 0)))That will subtract 32 from the red, 0 from the green, 0 from the blue.