This class will be recorded! Its use is limited to members of the class. Please do not share with others.
Approximate overview
@staff to work in the lab channel, feel
free to tag all three of us."Trying remove-spaces on \" hi \"" appear
as "Trying remove-spaces on \" hi \"".Events
I’m not sure if all of these links are correct. Let me know if any are not.
Sam: Can we wait until a month from today to take the quiz?
Not if you want to earn points on the quiz.
let expressionslet expressionsHere’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.
let expressionsDoes that sound famililar? It should.
To evaluate a procedure call.
(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)
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 …]) …)).
(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?
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.