6.001 Recitation – April 18, 2003

 

RI: Konrad Tollmar

 

• Streams

• Concurrency

 

1. Create Infinite Streams

 

 

(define (cons-stream x (y lazy-memo))

   (cons x y))

(define stream-car car)

(define stream-cdr cdr)

 

 

 

(define (stream-interval a b)

   (if (> a b)

       the-empty-stream

       (cons-stream a (stream-interval (+ a 1) b))))

 

 

(define (stream-ref s n)

 (if (= n 0)

      (stream-car s)

      (stream-ref (stream-cdr s) (- n 1))))

 

(define (stream-filter pred stream)

  (cond ((stream-null? stream) the-empty-stream)

        ((pred (stream-car stream))

         (cons-stream (stream-car stream)

                      (stream-filter pred

                                     (stream-cdr stream))))

        (else (stream-filter pred (stream-cdr stream)))))

 

(define (add-streams s1 s2)

   (cons-stream (+ (stream-car s1) (stream-car s2))

                         (add-streams (stream-cdr s1) (stream-cdr s2)))))

 

 

Show how we could create a stream of integers in an alternative way,
given the stream ones (1 1 1 1 ….) and the procedure add-streams.

 

(define seq (stream-interval 1 10))

 

(define (integers-starting-from n)

  (cons-stream n (integers-starting-from (+ n 1))))

 

(define integers (integers-starting-from 1))

 

(define ones (cons-streams 1 ones))

 

 

(define integers

   (cons-stream 1

          (add-streams ones integers))

 

(define (divisible? x y) (= (remainder x y) 0))

 

(define no-sevens

  (stream-filter (lambda (x) (not (divisible? x 7)))

                 integers))

 

 

 

 


2. Define Fibonacci numbers with stream.

Write a procedure, (fibs), that returns a stream of Fibonacci numbers. The Fibonacci series goes

 

 

    (0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 ...)

 

It starts with two 1's, then each successive value is the sum of the previous two.

 

 

Hint: use add-streams

 

F(n) = F(n-2) + F(n-1)

 

 (define fibs

       (cons-stream

         0

         (cons-stream

           1

           (add-stream (stream-cdr fibs) fibs))))

 


3. Concurrency

 

(define (make-serializer)

  (let ((mutex (make-mutex)))

    (lambda (p)

      (define (serialized-p . args)

        (mutex 'acquire)

        (let ((val (apply p args)))

          (mutex 'release)

          val))

      serialized-p)))

 

(define (make-mutex)

  (let ((cell (list false)))           

    (define (the-mutex m)

      (cond ((eq? m 'acquire)

             (if (test-and-set! cell)

                 (the-mutex 'acquire)))

            ((eq? m 'release) (clear! cell))))

    the-mutex))

 

(define (clear! cell)

  (set-car! cell false))

 

(define (test-and-set! cell)

  (if (car cell)

      true

      (begin (set-car! cell true)

             false)))

 

;;from footnote -- MIT Scheme

(define (test-and-set! cell)

  (without-interrupts

   (lambda ()

     (if (car cell)

         true

         (begin (set-car! cell true)

                false)))))

 

Give all possible values of x that can result from execution the following:

 

(define x 10)

 

(define p (lambda () (set! x (* x x))))

(define q (lambda () (set! x (+ x x x))))

 

(parallel-execute p q)

 

And if we instead use serialized procedures:

 

(define x 10)

(define s (make-serializer))

 

(define p (s (lambda () (set! x (* x x)))))

(define q (s (lambda () (set! x (+ x x x)))))

 

(parallel-execute p q)

 

2. Bank Accounts

 

(define (make-account-and-serializer balance)

  (define (deposit amount)

    (set! balance (+ balance amount))

    balance)

  (let ((balance-serializer (make-serializer)))

    (define (dispatch m)

      (cond ((eq? m 'deposit) (balance-serializer deposit))

            ((eq? m 'balance) balance)

            ((eq? m 'serializer) balance-serializer)

            (else (error "Unknown request -- MAKE-ACCOUNT"

                         m))))

    dispatch))

 

(define (get-balance acct)

  (acct ‘balance))

 

(define (deposit acct amount)

  (let ((d (acct ‘deposite)))

   (d amount)))

 

(define a (make-account 100))

 

Make deposite safe by use serialize

 

(define (deposit acct amount)

  (let ((s (acct ‘serialize)))

        (d (acct ‘deposite)))

   ((s d) amount)))

 

Do we need to redefine get-balance in the same way?

 

č    No, because balance is always a reasonable value.

 

3. Exchange Accounts

 

(define a (make-account 100))

(define b (make-account 50))

(exchange a b)

(get-balance a) -> 50

(get-balance b) -> 100

 

(define (exchange a1 a2)

  (let ((diff (- (a1 ‘balance) (a2 ‘balance)))

    ((a1 ‘deposite (- diff))

    ((a2 ‘deposite) diff)))

 

(define (serialized-exchange account1 account2)

  (let ((serializer1 (account1 'serializer))

        (serializer2 (account2 'serializer)))

    ((serializer1 (serializer2 exchange))

     account1

     account2)))

 

(define s (make-serializer))

(define t (make-serializer))

 

(s proc) -> serialized proc

(s ‘id) -> 1

(t ‘id) -> 2

 

 

(define (serialized-exchange account1 account2)

  (let ((serializer1 (account1 'serializer))

        (serializer2 (account2 'serializer)))

    ((if (< (serializer1 ‘id) (serializer2 ‘id))

            (serializer1 (serializer2 exchange))

            (serializer2 (serializer1 exchange))

account1 account2)

))