UNB/ CS/ David Bremner/ teaching/ cs4613/ tutorials/ Lab Tutorial 4

Introduction

In today's tutorial you will use Boxes to implement circular data structures.

Start with the following plait code. The MList type represents a mutable list type, where the value representing the tail of a list can be replaced with set-box!. mlist transforms a regular plait list of numbers into this form, while take returns a plait list with up to k elements in it.

(define-type MList
  [MPair (n : Number) (tail : (Boxof MList))]
  [Empty])

(define (mlist lst)
  (cond
    [(empty? lst) (Empty)]
    [else (MPair (first lst) (box (mlist (rest lst))))]))

(test (mlist empty) (Empty))

(test (mlist '(1)) (MPair 1 (box (Empty))))
(test (mlist '(1 2)) (MPair 1 (box (MPair 2 (box (Empty))))))

(define (take k mlst)
  (cond
    [(<= k 0) empty]
    [else
     (type-case MList mlst
       [(Empty) empty]
       [(MPair n tail-box)
        (cons n (take (sub1 k) (unbox tail-box)))])]))

(define big-mlist
  (mlist (build-list 50 identity)))

(test (take 10 big-mlist) '(0 1 2 3 4 5 6 7 8 9))

Write a function set-last! to update the tail field of the last pair in an MList. Your function should pass the following tests.

(define test-lst1 (mlist '(1 2 3)))
(define test-lst2 (mlist '(4 5 6)))
(set-last! test-lst1 test-lst2)
(test (take 6 test-lst1) '(1 2 3 4 5 6))
(test (take 3 test-lst2) '(4 5 6))
(test (take 1000 test-lst1) '(1 2 3 4 5 6))
(test/exn (set-last! (Empty) test-lst1) "cannot set tail")

Cyclic lists

Write a wrapper cycle around set-last! to make a cyclic list. Your function should pass the following tests.

(define small-cycle (cycle (mlist '(0 1 2))))
(define big-cycle (cycle big-mlist))
(test (cycle (Empty)) (Empty))
(test (take 0 big-cycle) empty)
(test (take 0 small-cycle) empty)
(test (take 5 big-cycle) '(0 1 2 3 4))
(test (take 5 small-cycle) '(0 1 2 0 1))
(test (take 107 big-cycle) (build-list 107 (lambda (n) (modulo n 50))))