summaryrefslogtreecommitdiffstats
path: root/ps02_generics/generic-sequences.scm
blob: 5e426cfc4c167ebf0e4b97708722bc30bc593759 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
;;;;    Generic sequence operator definitions

;;; First we declare the operators we want to be generic.
;;;  Each declaration specifies the arity (number of arguments)
;;;  and the default operation, if necessary.

(define sequence:null
  (make-generic-operator 1 #f))


(define sequence:ref
  (make-generic-operator 2 #f))

(define sequence:size
  (make-generic-operator 1 #f))

(define sequence:type
  (make-generic-operator 1 #f))

(define sequence:null?
  (make-generic-operator 1 #f))

(define sequence:equal?
  (make-generic-operator 2 #f))

(define sequence:set!
  (make-generic-operator 3 #f))

(define sequence:subsequence
  (make-generic-operator 3 #f))


;;; sequence:append takes multiple arguments.  It is defined in terms
;;; of a binary generic append that takes a sequence and a list of sequences.

(define (sequence:append . sequences)
  (if (null? sequences)
      (error "Need at least one sequence for append"))
  (let ((type? (sequence:type (car sequences))))
    (if (not (for-all? (cdr sequences) type?))
	(error "All sequences for append must be of the same type"
	       sequences))
    (fold-right generic:binary-append
		(sequence:null (sequence:type (car sequences)))
		sequences)))

(define generic:binary-append (make-generic-operator 2 #f))

;;; Implementations of the generic operators.

(define (any? x) #t)
(define (constant val) (lambda (x) val))
(define (is-exactly val) (lambda (x) (eq? x val)))

(assign-operation sequence:null (constant "")    (is-exactly string?))
(assign-operation sequence:null (constant '())   (is-exactly list?))
(assign-operation sequence:null (constant #())   (is-exactly vector?))

(assign-operation sequence:ref string-ref         string? exact-integer?)
(assign-operation sequence:ref list-ref           list?   exact-integer?)
(assign-operation sequence:ref vector-ref         vector? exact-integer?)

(assign-operation sequence:size string-length     string?)
(assign-operation sequence:size length            list?)
(assign-operation sequence:size vector-length     vector?)

(assign-operation sequence:type (constant string?)     string?)
(assign-operation sequence:type (constant list?)       list?)
(assign-operation sequence:type (constant vector?)     vector?)


(define (vector-null? v) (= (vector-length v) 0))

(assign-operation sequence:null? string-null?     string?)
(assign-operation sequence:null? null?            list?)
(assign-operation sequence:null? vector-null?     vector?)


;;; To assign to the ith element of a list:

(define (list-set! list i val)
  (cond ((null? list)
	 (error "List does not have enough elements" i))
	((= i 0) (set-car! list val))
	(else (list-set! (cdr list) (- i 1) val))))

(assign-operation sequence:set! string-set!   string? exact-integer? any?)
(assign-operation sequence:set! list-set!     list?   exact-integer? any?)
(assign-operation sequence:set! vector-set!   vector? exact-integer? any?)


(assign-operation sequence:subsequence
		  substring
		  string?  exact-integer?  exact-integer?)
(assign-operation sequence:subsequence
		  sublist
		  list?  exact-integer?  exact-integer?)
(assign-operation sequence:subsequence
		  subvector
		  vector?  exact-integer?  exact-integer?)


(define (vector-append v1 v2)
  (let ((n1 (vector-length v1))
	(n2 (vector-length v2)))
    (make-initialized-vector (+ n1 n2)
			     (lambda (i)
			       (if (< i n1)
				   (vector-ref v1 i)
				   (vector-ref v2 (- i n1)))))))

(assign-operation generic:binary-append string-append  string? string?)
(assign-operation generic:binary-append append         list?   list?)
(assign-operation generic:binary-append vector-append  vector? vector?)