Activity: Higher Order Functions
Table of Contents
1 Activity structure
This is an activity not an assignment. That means it is not a graded assessment: you won't get formal feedback on it, but it is a great chance to practice with the ideas we've been talking about and it may also guide you through some new ideas. You'll work on it during class, usually with another students, or if you have to miss class, you'll complete it outside of class.
If you're working with someone, you should work in a paired programming style. At any point in time, one of you is "driving," i.e. actually using the keyboard and mouse. The other is actively engaged following along, preventing bugs, and providing ideas. You'll tradeoff who is driving about every 10 minutes, and it's important that regardless of whose computer you're using, you take turns typing and controlling it - the owner of the computer should not be the only one who drives. Before you start coding for a new part of the activity, I strongly encourage you to sketch out your strategy with your partner. You might discuss possible approaches together, and write down some ideas on paper that will then help you when you begin coding.
At the end of class, you should make sure you turn your code in (even if you're not done), as that gives you access to my solutions, and to email the code to your partner (so they can turn it in to access my solutions).
2 Setup
If both you and your partner have computers with you with the tools for our class setup on it, decide whose computer you'll be using.
Them you'll do the activity in VS Code: download the starter code (below), unzip it, move it into the ProgrammingLanguages folder for our docker container, and then open that folder as a docker in VSCode.
<<<<<<< HEAD Click here to access the starter code for this activity. ======= Click here to access the starter code for this activity. >>>>>>> dev
3 Tasks
Put all of your code for these tasks in main.scm
. Put written
answers in WrittenAnswers.txt
.
3.1 map practice
- Here's some Scheme code:
(map (lambda (item) (+ 2 item)) '(1 4 7 10))
What will this expression evaluate to? Try to figure it out without
using the interpreter. Write your answer in
WrittenAnswers.txt
. After you've come up with an answer, check your answers in Guile by running the input; you'll need to
use the following line first to tell Guile to use a module:
(use-modules (rnrs))
3.2 fold-left
Recall that Scheme has two versions of a reduce-like
function: fold-left
and fold-right
. fold-left
applies the reduction from left to right,
while fold-right
applies the reduction from right to left (although as
usual, it is always initially accessing the Scheme list from left to
right). Here are a couple of inputs and expected outputs for fold-left
:
(fold-left + 3 '(7 0 4)) ;; Returns 14 (fold-left - 3 '(7 0 4)) ;; Returns -8 (fold-left cons 3 '(7 0 4)) ;; Returns (((3 . 7) . 0) . 4)
Make sure you can explain why fold-left returns each of the outputs above for these examples.
3.2.1 input/output practice
Determine the correct outputs for the following inputs (make sure you come up with an answer before you run these!):
(fold-left * 3 '()) (fold-left - 8 '(1 -3 5)) (fold-left cons 7 '((1 . 2) 3))
Write each input and the expected output in WrittenAnswers.txt. As above, you can check your answers in Guile by running the input. Make sure you've told Guile to use the module:
(use-modules (rnrs))
3.2.2 Using fold-left
Imagine I want to sum up all the entries in a list that are less
than 10. For example, if I had the list (10 5 9 20 25 2 35)
, I'd
want to get 16, since 5+9+2=16
.
In main.scm
, write a Scheme function sum-small
to accomplish your task. The
function should take a single input, the list to sum up, and it should
use fold-left
. I'd call it like:
(sum-small '(10 5 9 20 25 2 35))
Not sure where to start? Here's the skeleton of my code:
(define sum-small (lambda (lst) (fold-left (lambda (cur-total next-item) [FUNCTION BODY - you'll fill this in!]) FILL-IN lst)))
You'll fill in the function body and the second input to fold-left
marked FILL-IN above.
3.2.3 Implementing fold-left
You'll now write your own version of fold-left
, which we'll call
fold-l
. First, brainstorm what the base case(s) and recursive case(s)
are, and then write your code in main.scm
. Test your code on the examples
above. If you wish, you can add your own tests to
tests-activity.scm
, and then you can run these tests with ./test-activity
; look at
mine for examples of the syntax, and feel free to ask for help if you
get stuck!
3.3 fold-right
Now, you'll do the same thing for fold-right. To remind yourself what fold-right does and how it differs from fold-left, here are a couple of examples of inputs and outputs from fold-right:
(fold-right cons 3 '(7 0 4)) ;; Returns (7 0 4 . 3) (fold-right list '(1) '(21 22 23)) ;; Returns (21 (22 (23 (1))))
Before you start writing code, determine the correct outputs for the following inputs (make sure you come up with an answer before you run these!):
(fold-right cons '(1 2) '(10 11 12)) (fold-right list 4 '(3))
Write each input and the expected output in WrittenAnswers.txt. As
above, you can check your answers in Guile if you use the rnrs
module.
Now, write your own version fold-right, which we'll call fold-r
. As
above, brainstorm what the base case(s) and recursive case(s) should
be, and then write your code in main.scm
. Test your code using a
variety of inputs and outputs.
3.4 Extra time?
If you have extra time, write two functions: reverse-fold-l
and
reverse-fold-r
. Each of these functions takes a list as input, and
returns the reverse of that list as output. reverse-fold-l
should
call the fold-l
function, while reverse-fold-r
should call the
fold-r
function.
Hint: My implementation of each of these includes a single call to
fold-l
or fold-r
, and defines a function using lambda
to pass in
to fold-l
or fold-r
. One note that may be helpful: the base case
of append
is such that (append '() 'whatever)
evaluates to
whatever
(i.e., appending to an empty list simply returns wht you're
appending to - you might consider how to implement append for why this
is the case).
4 Turning in activities
To turn in this activity, zip up the folder with your code, and upload that zip on Moodle. Additionally, email the zip to your partner so they can turn it in too. Even if you worked with a partner or you didn't finish, everyone should turn in the activity in order to gain access to my solutions.