EBoard 13: Local bindings

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

Approximate overview

  • Lab [~30 min]
  • Administrative stuff [~10 min]
  • Q&A [~10 min]
  • Quiz [~10 min]
  • Tracing local bindings [~15 min]
  • Lab [~? min]

Administrative stuff

Notes and News

  • New arrangement of class today!
  • I’m still working from home today. I have no explanation. (Well, it was easier to deal with grant reviews from home.)
  • DrRacket just evolved to version 8.0. I recommend that you stay with version 7.9 for now.
  • Evening tutoring is available 3-5 p.m. Sundays and 7-10 p.m. Sundays through Thursdays in the tutoring channel on the CS team.
    • If evening tutors + mentor sessions are not enough, we do have individual tutors available.
    • Evening tutors like visitors, including in-person visitors.
  • If you can’t get get @staff to work in the lab channel, feel free to tag all three of us.
  • Office hours generally get booked through https://bit.ly/book-samr.
  • Important: The graders insert comments in your code. Please read them.
    • If you see a grader’s name, please let me know.
  • IF ONE OF YOUR PARTNERS DOES NOT FEEL COMFORTABLE GOING ON TO THE NEXT PROBLEM, DO NOT GO ON WITHOUT THEM!
    • If you need some help negotiating situations like this, please call one of the staff in.

The never-ending war with the autograder

  • Sorry for the autograder delay. I wish I could say that things were getting better, but ….
  • If there’s an error in your code, you may get nothing at all for your tests.
  • Amusingly enough, the Gradescope procedure for displaying text collapses all sequences of spaces to a single space. I’m working on it. "Trying remove-spaces on \" hi \"" appear as "Trying remove-spaces on \" hi \"".

Upcoming activities and other token earning things

Events

  • CS Extras, 5pm, Thursday, 18 February, in Events Channel on CS Team. Random Higher-Order Network Generation
  • Get your free food from Chuong Garden Wednesday, Thursday, or Friday. (See note from Dean Marzluff on Announcements Channel.)
    • Yes, you have to write about the experience.
    • If you aren’t on campus, suggest an alternative.
  • Journalism Ethics Workshop, 7:00-8:30 pm, Thursday, March 4 and Tuesday, March 9

Upcoming work

I’m not sure if all of these links are correct. Let me know if any are not.

Attendance

  • Our wonderful mentors will take attendance by looking at the the list of also-wonderful people here.

Notes from the reading responses

Q&A

Sam: Can we wait until a month from today to take the quiz?

Not if you want to earn points on the quiz.

Quiz

  • Students should return to class after the quiz.

Tracing let expressions

The form of let expressions

Here’s the standard form of a let expression.

(let ([NAME1 EXP1]
      [NAME2 EXP2]
      ...
      [NAMEn EXPn])
  BODY1
  BODY2
  ...
  BODYm)

In most cases, we only have one body in the expression.

A substitutive mental model that lets us trace executution may help us understand things better.

Tracing let expressions

  • Evaluate all of the expressions in the bindings.
  • Substitute the bound values for the corresponding variables in the body.
  • Evaluate the expressions in the body. (Usually there’s just one.)
  • Return the value of the last body expression.

Does that sound famililar? It should.

  • Yes
  • But I can’t tell why.
  • It sounds like algebra. All CS sounds like algebra.
  • It sounds like what we do with procedures.

To evaluate a procedure call.

  • Evaluate all of the argument expressions.
  • Substitute the arguments for the corresponding parameters in the body.
  • Evaluate the body.

Followup

(let ([NAME1 EXP1]
      [NAME2 EXP2]
      ...
      [NAMEn EXPn])
  BODY1
  BODY2
  ...
  BODYm)
(define proc
  (lambda (NAME1 NAME2 ... NAMEn)
    BODY1
    BODY2
    ...
    BODYm))
(proc EXP1 EXP2 ... EXPn)

We will trace let expressions much like we trace procedure calls.

((lambda (NAME1 NAME2 ... NAMEn) BODY ... BODYm)
 EXP1 EXP2 ... EXPN)

Example of tracing let.

(define a 1)
(define b 2)
(define c 3)

(let ([a 10])
  (let ([b (* a a)])
    (let ([c (+ b a)])
      (list a b c))))

Let’s trace

    (let ([a 10])
      (let ([b (* a a)])
        (let ([c (+ b a)])
          (list a b c))))
    ; Note: The body of the (let ([a 10]) ... is the (let ([b ...]) ...))
--> (let ([b (* 10 10)])
      (let ([c (+ b 10)])
        (list 10 b c))))
    ; Evaluate the (* 10 10)
--> (let ([b 100])
      (let ([c (+ b 10)])
        (list 10 b c))))
    ; Fill in the b's
--> (let ([c (+ 100 10)])
      (list 10 100 c))))
    ; Evaluate the expression next to c
--> (let ([c 110])
      (list 10 100 c))))
--> (list 10 100 110)
--> '(10 100 110)

Let’s trace!

(define a 1)
(define b 2)
(define c 3)
    (let ([a 10]
          [b (* a a)]
          [c (+ b a)])
      (list a b c))
    ; Evaluate the expression corresponding to a.  (That's 10.)
--> (let ([a 10]
          [b (* a a)]
          [c (+ b a)])
      (list a b c))
    ; Substitute 10 for a and get rid of the (let [a 10
--> (let ([b (* 10 10)]
          [c (+ b 10)])
      (list 10 b c))
    ; Evaluate the expression that corresponds to b: (* 10 10)
--> (let ([b 100]
          [c (+ b 10)])
      (list 10 b c))
    ; Substitute 100 for b
--> (let ([c (+ 100 10)])
      (list 10 100 c))

WHOOPS! WE WENT ASTRAY.

(define a 1)
(define b 2)
(define c 3)
    (let ([a 10]
          [b (* a a)]
          [c (+ b a)])
      (list a b c))
    ; Evaluate the expression corresponding to a.  (That's 10.)
--> (let ([a 10]
          [b (* a a)]
          [c (+ b a)])
      (list a b c))
    ; Evaluate the expression for (* a a)
    ; Step 1, look up the first a
--> (let ([a 10]
          [b (* 1 a)]
          [c (+ b a)])
      (list a b c))
--> (let ([a 10]
          [b (* 1 1)]
          [c (+ b a)])
      (list a b c))
--> (let ([a 10]
          [b 1]
          [c (+ b a)])
      (list a b c))
    ; Need to evaluate the (+ b a)
--> (let ([a 10]
          [b 1]
          [c (+ 2 1)])
      (list a b c))
--> (let ([a 10]
          [b 1]
          [c 3])
      (list a b c))
    ; Substitute into the list
--> (list 10 1 3)
--> '(10 1 3)
(define a 1)
(define b 2)
(define c 3)
    (let* ([a 10]
           [b (* a a)]
           [c (+ b a)])
      (list a b c))
    ; Evaluate the expression corresponding to a.  (That's 10.)
--> (let* ([a 10]
           [b (* a a)]
           [c (+ b a)])
      (list a b c))
    ; Substitute 10 for a and get rid of the (let [a 10
--> (let* ([b (* 10 10)]
           [c (+ b 10)])
      (list 10 b c))
    ; Evaluate the expression that corresponds to b: (* 10 10)
--> (let* ([b 100]
           [c (+ b 10)])
      (list 10 b c))
    ; Substitute 100 for b
--> (let* ([c (+ 100 10)])
      (list 10 100 c))
    ; Evaluate the (+ 100 10)
--> (let* ([c 110])
      (list 10 100 c))
    ; Replace!
--> (list 10 100 110))
--> '(10 100 110))

Interesting: (let* ([a …] [b …] …)) is the same as (let ([a …]) (let ([b …]) …)).

A strange problem

(define years-to-seconds-a
  (lambda (years)
    (verbose-let* ([days-per-year 365.24]
           [hours-per-day 24]
           [minutes-per-hour 60]
           [seconds-per-minute 60]
           [seconds-per-year (* days-per-year hours-per-day
                                minutes-per-hour seconds-per-minute)])
      (* years seconds-per-year))))

(define years-to-seconds-b
  (verbose-let* ([days-per-year 365.24]
         [hours-per-day 24]
         [minutes-per-hour 60]
         [seconds-per-minute 60]
         [seconds-per-year (* days-per-year hours-per-day
                              minutes-per-hour seconds-per-minute)])
    (lambda (years)
      (* years seconds-per-year))))

In the first case, the let is inside the lambda, in the second case, the let is outside the lambda.

What difference might that make?

  • In years-to-seconds-b, the definition only applies within the body.

Which printed all of the bindings when I hit run? years-to-seconds-b.

Which prints the bindings when I evaluate? years-to-seconds-a.

Each time I run years-to-seconds-a, it repeats the same work of computing secons-per year.

years-to-seconds-b only does that work once.