EBoard 16: Recursion

This class will be recorded! Its use is limited to members of the class. Please do not share with others.

Approximate overview

  • General administrative stuff [~10 min]
  • Q&A (not on recursion) [~10 min]
  • Quiz [~5 min]
  • Tracing let expressions [~? min]
  • Working with lists [~? min]
  • Talk about recursion [~? min]
  • Short lab [~? min]

Administrative stuff

Notes and news

  • As the overview suggests, today is mostly a talk day.
    • I’ll be trying to get you to talk, too.
  • Don’t forget to register for CSC 161. Weinman is awesome.
  • I’d like to hear from more of you in class! Volunteer ideas, questions, whatever.

Tutoring reminders

  • Please use our tutors! They like to work.
  • Evening tutoring will be available
    • 8-10 p.m. Sundays through Thursdays
    • 3-5 p.m. Sundays
    • In the “Drop in tutoring” channel on the CS team.
    • Sam will generally not be available during these times.
  • Individual tutors are also available.

Upcoming activities

Attend (or watch recording) and send a one-paragraph reflection.

  • Noon, TODAY, Convocation (+1 token)
    • “Do you have One Hour to Give to Save a Life? QPR is the CPR of Mental Health”
    • One of the more important Convos I’m recommending (even though it isn’t quite a convo)
    • Link posted
    • Here’s the info I got
      • Do you have one hour to give to save a life?
      • QPR is the CPR of Mental Health
      • Online learning includes
        • How to get help for yourself or learn more about preventing suicide
        • The common causes of suicidal behavior
        • The warning signs of suicide
        • How to Question, Persuade[,] and Refer someone who may be suicidal
        • How to get help for someone in crisis
  • 7:00 p.m. TONIGHT, Open Mic night. [+1 token for attending or performing]
    • No, it’s not live surgery on a guy named “Mike”
    • Lots of cool performances
  • Noon, Friday, The Future of the Humanities.
  • 3:30, Saturday, Nov. 21st: Maker Space (+1 token)
  • 7:30-9:30 p.m. Saturday, 21 Nov 2020: Art SEPC Collage, Meet, and Greet (+1 token)

Upcoming work

  • Mini-project 3 (due TONIGHT at 10:30 p.m. CST)
    • Because Sam posted the turn-in to Gradescope late, you get a free 24-hour extension.
  • Redo of Mini-project 2 (due Sunday the 22nd at 10:30 p.m. CST)
    • You need that back.
  • Reading for Friday
  • Quiz today: Testing. You’ll write tests for a procedure given its documentation
  • Quiz tomorrow: Reading or reflecting on recursion.
  • Quiz makeups: Coming soon.
  • MP4: Coming soon.
  • SoLA2: Tuesday.

Q&A

Next Term

I love making fun of you in the chat. I can’t imagine CS without that. Will you teach us 161 next term?

No. Weinman is awesome.

I’m a masochist and want to continue the abuse and high workload you heap on us. Will you teach us 161 next term?

See above.

Tell us about CSC-282, Thinking in C and Unix

It’s mostly designed for upper-level CS students. My experience is that there are gaps in their knowledge. This course eliminates some of those gaps.

Those who take CSC 161 in Spring 1 can register, but I expect that it will be more useful later in your career.

Tell us about CSC/PSY/TEC-232, Human-Computer Interaction

Not a programming class.

An opportunity to think/talk/read through how we build software (or other technologies) that normal people can use.

Ideally: Brings together students with different skills in projects.

I already know C/Java/everything you could ever want to teach me. Can I skip 161/207/the whole CS major?

We tend to do personal interviews to determine whether or not you should take or skip a CS course.

Recursion

Will you teach us recursion?

See below.

Will you teach us recursion?

See above.

No other questions on recursion permitted. We’ll talk about it and you’ll do lab and things will get clearer.

Miscellaneous

Do you look at what the formatted eboards look like?

Not normally. I trust my awesome markdown skills.

More seriously, I trust that you’ll tell me if I’ve screwed up the formatting.

Why do you make “jokes” (scare quotes intentional) in the Q&A section?

Why not?

Quiz

  • Don’t forget to bring up
    • The notes on testing
    • Your lab writeup from Tuesday
    • DrRacket (in case you want to do some experimentation)
    • Anything else you think may be of use
  • Not Discord (or anything similar). Other people are not valid resources.

Tracing let expressions

About quizzes

  • Quizzes serve multiple purposes.
    • “Low stakes” way for you to see how you’re doing.
    • A way for me to see what people are missing.
  • Results on let trace suggest a few issues (which may be time related).
  • The makeup will be for tomorrow. No token required. (If I use up a token, let me know.)

About tracing

  • We’re going to be doing a bunch of tracing in this class.
  • Tracing helps you develop a mental model of what the computer is doing.
  • Tracing can provide a way to debug / understand your code.
    • I like tracing as a way of understanding where your understanding has gone wrong.
  • Tracing may help us better understand recursion.
    • Our experience: Grinnell students generally find recursion natural. Students at many other institutions find it hard.
    • It’s okay if you find it hard. It’s one of the reasons we trace.
  • An important aspect of tracing: At any stage, we should be able to enter the current expression into DrRacket and get the same answer as we got for the original expression.
    • If not, our understanding was off.
    • We can then identify when our understanding went wrong.

How to trace in Scheme/Racket

  • Two basic principles
    • For procedures, evaluate all of the parameters before applying the procedure.
    • To apply a lambda procedure, replace the procedure call with the body of the procedure and replace the parameters (“formals”) with the arguments (“actuals”) in the body.
  • First two variations
    • The body of a lambda does not get evaluated until it is applied.
    • The first parameter (the name) of a define does not get evaluated. The define does update a table of definitions (bindings).
  • Other variations? (“keywords”)
    • You get to come up with some. I’ll ask one student for something that does not follow the policy and often ask the next for the tracing policy.
    • (if TEST TRUEPART FALSEPART) : Do the TEST. Then either do the TRUEPART or the FALSEPART.
      • Evaluate and use the TRUEPART when the TEST is true (#t)
        • Also when it’s anything that’s “truish”
      • Evaluate and use the FALSEPART when the TEST is false (#f).
      • How does this differ from “normal” evaluation?
        • We evaluate the FALSEPART after we evaluate the TEST.
        • In fact, we don’t always evaluate the FALSEPART.
        • If we didn’t have this behavior, we would try to recurse and recurse and recurse.
    • (and EXP1 EXP2 ... EXPn): Evaluate each expression until (a) we find one that’s false or (b) we’ve evaluated all the expressions.
      • What do we do when an expression is false? The and immediately returns false (#f).
      • What do we do when we’ve evaluated all the expressions? Returns the value of the last case.
      • How does this differ from “normal” evaluation? Once again, we don’t necessarily evaluate all of the parameters. We stop as soon as we hit false. “Short circuit evaluation.”
        • Edge case: When we reach the last expression, it still returns #f, so it has evaluated all of them.
      • What is (and #t 'um 'um (+ 4 2))
        • false (#f) [+1] (argument: 'um is false)
        • true (#t)
        • 6 (6) (argument: 'um is not false, so it’s truish) [+2]
    • (not EXP): Evaluate the expression: If it gives a truish value, return false (#f), otherwise, return true (#t).
      • How does this differ from the normal evaluation strategy for procedures?
        • It doesn’t! (The evaluation strategy is the same.)
        • It returns the opposite.
        • What about (- EXP)?
        • So perhaps “not” is more general, since it can take any kind of expression as a parameter.
    • (or EXP1 EXP2 ... EXPn): Evaluate the expressions left to right until we get a truish, in which case we return the value. If we run out of expressions, we get false (#f). * (or #f (< 4 2)) * 'um [+1] * #f * (or #f (+ 4 2)) * 6 [+1.5] The winner * #t [+0.5] * “Love is the answer” The conceptual winner * (or) * False (#f) [+2] * Something empty (e.g., the empty list) * Error: “or expects at least one parameter”
    • (cond [GUARD1 EXP1a EXP1b ... EXP1x] [GUARD2 EXP2a EXP2b ... EXP2x] [ELSE ALTa ... ALTx])
      • cond has those weird boxed things.
      • Evaluate the guard of the first one. If the first guard holds, it evaluates the expressions. Otherwise, it goes on to the next boxed thing.
      • When we reach the else, it just does the expressions in the else box.
      • Note: Once we hit a true guard, we stop evaluating the rest
        (different than the normal model).
        • Stop with the first guard that holds (is truish).
        • Then evaluate the corresponding expressions.
        • If the guard doesn’t hold, we don’t evaluate the corresponding expressions.
      • Like a bunch of if statements
      • Does the guard have to be in parentheses
        • Yes [+many]
        • No [+4]
        • (cond ["hello" 1] [else "zebra"]) --> 1
        • (cond [is-the-world-round "yay"] [else "what world?")
      • Why does the cond have multiple expressions?
        • Because the designers of Scheme designed it that way.
        • The value of the cond is the value of the last expression in the sequence corresponding to the first guard that holds.
        • But all of them are evaluated.
      • Why write multiple expressions if you only want the value of the last?
        • Some expressions can have effects on the broader world.
      • If there are no corresponding expressions, it returns the value of the guard.
    • (let* ([NAME1 EXP1] [NAME2 EXP2] ... [NAMEn EXPn]) BODY)
    • (let ([NAME1 EXP1] [NAME2 EXP2] ... [NAMEn EXPn]) BODY)
  • Also some procedures that we apply slightly differently than lambdas
    • (o PROC1 PROC2 ... PROCn)
    • (section PROC PARAM <>) (and variants)

Cond example

> (define something
    (lambda (x)
      (cond
        [(odd? x)
         1
         2
         3]
        [(>= x 10)
         "hello"
         "goodbye"]
        [(= x 6)]
        [(* x 3)]
        [else
         "zebra"])))
> (something 5)
; Proposal 1: 1 2 3 [+1]
; Proposal 2: An error message [+2]
3
; Why?  3 is the last of the expressions
> (something 12)
; Proposal 1: "goodbye" [+1]  
; Proposal 2: "hello"
; Proposal 3: "You say goodbye, I say hello.  Hello hello."
"goodbye"
> (something 8) ; before we inserted the (* x 3)
; Proposal 1: "zebra" [+1]
; Proposal 2: "A horse of a different color"
"zebra"
> (something 6)
; Proposal 1: 'um [+1]
; Proposal 2: Nothing aka `#void`
; Proposal 3: Error
; Proposal 4: True (`#t`)
#t
> (something -4)
; Proposal 1: "Freudian slip"
; Proposal 2: 'um
; Proposal 3: "Zebra" [+2]
; Proposal 4: -12 [+2] -10
; Proposal 5: True (`#t`)
; Proposal 6: Error
-12
> (define x 2)
> (cond [> x 3 "hello"] [else "something else"])
; Proposal 1: Error [+2]
; Proposal 2: True (`#t`)
; Proposal 3: "hello"
; Note: No parens, doesn't apply the procedure
"hello"
; Note: Forgetting things in conds can give you really weird values.

Detour on tick marks

> (symbol? 'um)
#t
> (symbol? '())
#f
> (symbol? '23)
#f
> (symbol? 'our-mentors-are-plants)
#t

Q&A

Can you please give us a quiz on tracing tomorrow?

Maybe

When is the next mini-project going to be released? What is going to be like?

Hopefully less than #3. Tell me when it’s not.

What is “the normal model”?

The initial model.

“Evaluate all the paremeters before applying the procedure.”

How to evaluate the application of a lambda expression.

Example of the initial model.

(define fred
  (lambda (x)
    (+ (/ 1 x) (* x x))))

;     (fred (- 5 3))
; --> (fred 2)
; --> (+ (/ 1 2) (* 2 2))
; --> (+ 1/2 (* 2 2))
; --> (+ 1/2 4)
; --> 9/2 (or 4 1/2)

(define derf
  (lambda (x)
    (or (/ 1 x) (* x x))))

;     (derf (- 5 3))
; --> (derf 2)
; --> (or (/ 1 2) (* 2 2))
; --> (or 1/2 (* 2 2))
;  ; Note: We do not do the 2*2
; --> 1/2

(define name
  (lambda (x)
    (+ (* x x) (/ 1 x))))
;     (name 0)
; --> (+ (* 0 0) (/ 1 0))
; --> (+ 0 (/ 1 0))
; --> boom!  Illegal division

(define eman
  (lambda (x)
    (or (* x x) (/ 1 x))))
;     (eman 0)
; --> (or (* x x) (/ 1 x))
; --> (or 0 (/ 1 0))
; --> 0

“What a great idea for a quiz.”