Closures in Scheme
Andy Balaam
Contents
- Functions in functions
- Using outer symbols
- Returning functions
- Closures
- Uses
- Discussion
Functions in functions
(define (sum-of-squares x y)
(define (square a)
(* a a))
(define (sum b c)
(+ b c))
(sum (square x) (square y)))
Using outer symbols
(define (assert-equal a b)
(define (print-error)
(display a)
(display " is not equal to ")
(display b)
(newline))
(if (not (equal? a b)) (print-error) null))
> (assert-equal 3 (+ 1 2))
> (assert-equal 3 (+ 2 2))
3 is not equal to 4
Using outer symbols (2)
(define (circle-details r)
(define pi 3.14)
(define (area) (round (* pi r r)))
(define (circum) (round (* 2 pi r)))
(list (area) (circum)))
> (circle-details 3)
(28.0 19.0)
Returning functions
(define (make-add-one)
(define (inc x) (+ 1 x))
inc)
Returning functions (2)
> (make-add-one)
#<procedure:inc>
> (define myfn make-add-one)
> (myfn 2)
procedure make-add-one: expects no arguments, given 1
> (define myfn (make-add-one))
> (myfn 2)
3
Closures
(define (make-add-x x)
(define (add-x y) (+ x y))
add-x)
Closures (2)
> (define add-3 (make-add-x 3))
> add-3
#<procedure:add-x>
> (add-3 4)
7
Uses - Holding state
(define (make-counter)
(define value 0)
(define (counter)
(set! value (+ value 1))
value)
counter)
Uses - Holding state (2)
> (define mycounter1 (make-counter))
> (mycounter1)
1
> (mycounter1)
2
> (mycounter1)
3
Uses - Holding state (3)
> (define mycounter2 (make-counter))
> (mycounter2)
1
> (mycounter1)
4
> (mycounter2)
2
> (mycounter1)
5
Uses - Testing
(define (shout display-fn txt)
(display-fn
(list->string
(map
char-upcase
(string->list txt)))))
Uses - Testing (2)
> (shout display "boo")
BOO
Uses - Testing (3)
(define (test-shout-displays-upper-case)
(define displayed "")
(define (fake-display txt)
(set! displayed txt))
(shout fake-display "Hello Andy")
(assert-equal displayed "HELLO ANDY"))
Uses - Classes
(define (make-balance)
(define value 0)
(define (bal method)
(define (add-method x)
(set! value (+ value x)))
(define (get-method) value)
(if (equal? method "add")
add-method
get-method))
bal)
Uses - Classes (2)
> (define a (make-balance))
> (a "get")
#<procedure:get-method>
> ((a "get"))
0
> ((a "add") 3)
> ((a "get"))
3
Uses - Classes (3)
> (define b (make-balance))
> ((b "get"))
0
> ((b "add") -1)
> ((b "get"))
-1
> ((a "get"))
3
Discussion