#lang racket |
|
; using closures to capture and hide state |
|
; (hide-state) returns a closure that when invoked increments the |
; previous stored value and then returns it. The initial value is 0. |
|
(define hide-state |
(lambda () |
(let ( (internal 0) ) ; internal is not visible outside of hide-state |
(lambda () (set! internal (+ internal 1)) internal) |
) |
) |
) |
|
(display "hide-state")(newline) |
(define i (hide-state)) |
(i) |
(i) |
(i) |
|
; (make-counter init incr) returns a list of 3 closures. |
; the first returns the current value of the counter |
; the second adds incr and returns the current value |
; the third subtracts incr and returns the current value |
|
(define make-counter |
(lambda (init incr) |
(let ( (counter init) ) |
(list |
(lambda () counter) ; return the current value |
(lambda () (set! counter (+ counter incr)) counter) ; increment and return the current value |
(lambda () (set! counter (- counter incr)) counter) ; decrement and return the current value |
)))) |
|
(newline) |
(display "make-counter")(newline) |
(define counter (make-counter 5 3)) |
(define v (first counter)) |
(define v+ (second counter)) |
(define v- (third counter)) |
|
(v) |
(v+) |
(v) |
(v+) |
(v-) |
(v) |
(v-) |
#lang racket |
|
; The queue motivated by chapter 3 of SICP |
|
; a queue is a mutable pair, where the mcar is a pointer to the |
; front of the queue, and the mcdr is a pointer to the rear |
; of the queue. You insert at the rear (on the right) and remove |
; from the front (on the left). |
; The actual queue is a mutable-list formed by chaining mutable |
; pairs. |
|
(define (q-front-ptr queue) (mcar queue)) |
(define (q-rear-ptr queue) (mcdr queue)) |
(define (q-set-front-ptr! queue item) (set-mcar! queue item)) |
(define (q-set-rear-ptr! queue item) (set-mcdr! queue item)) |
(define (q-empty? queue) (null? (q-front-ptr queue))) |
(define (q-make) (mcons '() '()) ) |
(define (q-front queue) |
(if (q-empty? queue) |
(error "front-of-queue called with an empty queue" queue) |
(mcar (q-front-ptr queue)) |
) |
) |
|
(define (q-insert! queue item) |
(let ( (new-pair (mcons item '() ) ) ) |
(cond ( (q-empty? queue) |
(q-set-front-ptr! queue new-pair) |
(q-set-rear-ptr! queue new-pair) |
queue) |
(else |
(set-mcdr! (q-rear-ptr queue) new-pair) |
(q-set-rear-ptr! queue new-pair) |
queue) |
) |
) |
) |
|
(define (q-remove! queue) |
(cond ( (q-empty? queue) |
(error "remove-queue! called with an empty queue" queue) |
) |
(else |
(let ( (front (mcar (q-front-ptr queue))) ) |
(q-set-front-ptr! queue (mcdr (q-front-ptr queue))) |
front) |
) |
) |
) |
|
(define q (q-make)) |
(q-insert! q 1) |
(q-front q) |
(q-insert! (q-insert! q 2) 3) |
(q-front q) |
(q-remove! q) |
(q-remove! q) |
|
|
;(define (q-to-list q) ) |
;(define (q-from-list l) ) |
#lang racket |
|
; example of implementing your own delay/force |
; a promise is a mutable pair |
; if the first is 0, the second is a lambda () that when evaluated |
; gives the value of the promise |
; if the first is 1, the second is the actual value of the promise |
; |
; |
(define (pdelay x) (mcons 0 (lambda () x))) |
(define (pforce promise) |
(if (= 1 (mcar promise)) |
; already got value memoized |
(mcdr promise) |
; evaluate the promise and memoize it |
(begin (set-mcar! promise 1) |
(set-mcdr! promise ((mcdr promise))) |
(mcdr promise)) |
) |
) |