(load "~/classes/symbolic/psets/02/ghelper.scm")
(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))
(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))
(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?)
(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?)
(define (all? pred)
(lambda (x)
(for-all? x pred)))
(define (applier fn)
(lambda (x)
(apply fn x)))
(define (select-from-pair fn)
(lambda (x y)
(if (fn x y)
x
y)))
(define (of-arity? n)
(lambda (fn)
(procedure-of-arity? fn n)))
(define (there-exists? lis pred?)
(let loop ((lis lis))
(cond ((null? lis)
#f)
((pred? (car lis))
#t)
(else
(loop (cdr lis))))))
(define (reverse-arguments f)
(lambda args
(apply f (reverse args))))
(define sequence:from-list
(make-generic-operator 2 #f))
(assign-operation sequence:from-list ((discard-argument 0) list->string) (is-exactly string?) (all? char?))
(assign-operation sequence:from-list ((discard-argument 0) identity) (is-exactly list?) any?)
(assign-operation sequence:from-list ((discard-argument 0) list->vector) (is-exactly vector?) any?)
(define sequence:to-list
(make-generic-operator 1 #f))
(assign-operation sequence:to-list identity list?)
(assign-operation sequence:to-list vector->list vector?)
(assign-operation sequence:to-list string->list string?)
(define (sequence:internal-do-coerce type? sequence)
(sequence:from-list type?
(sequence:to-list sequence)))
(define sequence:coerce
(make-generic-operator 2 #f))
(assign-operation sequence:coerce ((discard-argument 0) identity) (is-exactly list?) list?)
(assign-operation sequence:coerce ((discard-argument 0) vector->list) (is-exactly list?) vector?)
(assign-operation sequence:coerce ((discard-argument 0) string->list) (is-exactly list?) string?)
(assign-operation sequence:coerce ((discard-argument 0) list->vector) (is-exactly vector?) list?)
(assign-operation sequence:coerce ((discard-argument 0) identity) (is-exactly vector?) vector?)
(assign-operation sequence:coerce sequence:internal-do-coerce (is-exactly vector?) string?)
(assign-operation sequence:coerce ((discard-argument 0) list->string) (is-exactly string?) list?)
(assign-operation sequence:coerce sequence:internal-do-coerce (is-exactly string?) vector?)
(assign-operation sequence:coerce ((discard-argument 0) identity) (is-exactly string?) string?)
(define (sequence:coercer type?)
(lambda (sequence)
(sequence:coerce type? sequence)))
(sequence:to-list '(1 2 3))
(sequence:to-list '#(1 2 3))
(sequence:to-list "foo")
(sequence:from-list list? (sequence:to-list '(1 2 3)))
(sequence:from-list vector? (sequence:to-list '#(1 2 3)))
(sequence:from-list string? (sequence:to-list "foo"))
(sequence:coerce list? '(1 2 3))
(sequence:coerce list? '#(1 2 3))
(sequence:coerce list? "foo")
(sequence:coerce vector? '(1 2 3))
(sequence:coerce vector? '#(1 2 3))
(sequence:coerce vector? "abc")
(sequence:coerce string? '(#\a #\b #\c))
(sequence:coerce string? '#(#\a #\b #\c))
(sequence:coerce string? "abc")
((sequence:coercer list?) '#(1 2 3))
((sequence:coercer vector?) "abc")
((sequence:coercer string?) '(#\a #\b #\c))
(define (sequence:construct type? . elements)
(sequence:from-list type? elements))
(sequence:construct vector? 1 2 3)
(sequence:construct list? 1 2 3)
(sequence:construct string? #\f #\o #\o)
||#
(sequence:null string?)
(sequence:null list?)
(sequence:null vector?)
|#
(sequence:ref '(1 2 3) 1)
(sequence:ref '#(1 2 3) 1)
(sequence:ref "foo" 1)
||#
(sequence:size '(1 2 3))
(sequence:size '#(1 2 3))
(sequence:size "foo")
||#
((sequence:type '(1 2 3)) '(1 2 3))
((sequence:type '(1 2 3)) "foo")
((sequence:type '#(1 2 3)) '#(1 2 3))
((sequence:type '#(1 2 3)) '(1 2 3))
((sequence:type "foo") "foo")
((sequence:type "foo") '#(1 2 3))
||#
(sequence:null? '(1 2 3))
(sequence:null? '())
(sequence:null? '#(1 2 3))
(sequence:null? '#())
(sequence:null? "foo")
(sequence:null? "")
||#
(assign-operation sequence:equal? equal? list? list?)
(assign-operation sequence:equal? equal? vector? vector?)
(assign-operation sequence:equal? equal? string? string?)
(sequence:equal? '(1 2 3) '(1 2 3))
(sequence:equal? '(1 2 3) '(1 2))
(sequence:equal? '#(1 2 3) '#(1 2 3))
(sequence:equal? '#(1 2 3) '#(1 2))
(sequence:equal? "123" "123")
(sequence:equal? "123" "12")
(assign-operation sequence:set! list-set! list? exact-integer? any?)
(assign-operation sequence:set! vector-set! vector? exact-integer? any?)
(assign-operation sequence:set! string-set! string? exact-integer? char?)
(define foo '(1 2 3))
(sequence:set! foo 1 'a)
foo
(define bar '#(1 2 3))
(sequence:set! bar 1 'a)
bar
(define baz "123")
(sequence:set! baz 1 #\a)
baz
(sequence:subsequence (iota 10) 3 7)
(sequence:subsequence (list->vector (iota 10)) 3 7)
(sequence:subsequence (list->string
(map digit->char
(iota 10)))
3 7)
(sequence:append (iota 3 0)
(iota 7 4)
(iota 10 8))
(sequence:append "foo " "bar " "baz ")
(apply
sequence:append (map list->vector
(list (iota 3 0)
(iota 7 4)
(iota 10 8))))
(define (sequence:internal-do-generate type? n fn)
(sequence:from-list type? (map fn (iota n))))
(define sequence:generate
(make-generic-operator 3 #f))
(assign-operation sequence:generate
sequence:internal-do-generate
(is-exactly list?)
exact-integer?
(of-arity? 1))
(assign-operation sequence:generate
sequence:internal-do-generate
(is-exactly vector?)
exact-integer?
(of-arity? 1))
(assign-operation sequence:generate
sequence:internal-do-generate
(is-exactly string?)
exact-integer?
(of-arity? 1))
(sequence:generate list? 5 square)
(sequence:generate vector? 5 square)
(sequence:generate string? 5 digit->char)
(define (sequence:map fn . sequences)
(cond ((null? sequences)
(error "sequence:map : Need at least one sequence for map"))
((not (procedure? fn))
(error "sequence:map : Cannot map a non-procedure"))
((not (procedure-of-arity? fn (length sequences)))
(error "sequence:map : Cannot map procedure -- not of arity" (length sequences)))
((not (apply = (map sequence:size sequences)))
(error "sequence:map : Cannot map onto sequences of different length"))
(else
(let ((type? (sequence:type (car sequences))))
(if (not (for-all? (cdr sequences) type?))
(error "sequence:map : All sequences for map must be of the same type"
sequences))
(sequence:from-list type?
(apply map fn
(map sequence:to-list
sequences)))))))
(sequence:map + '(1 2 3) '(5 5 5))
(sequence:map + '#(1 2 3) '#(5 5 5))
(sequence:map (select-from-pair char<=?) "abcde" "ccccc")
(sequence:map + '(1 2 3) '(5 5))
(sequence:map +)
(sequence:map 3 '(1 2 3) '(5 5 5))
(sequence:map sqrt '(1 2 3) '(5 5 5))
(define (apply-display fn)
(lambda args
(display (apply fn args))))
(define (sequence:for-each fn . sequences)
(cond ((null? sequences)
(error "sequence:for-each : Need at least one sequence for for-each"))
((not (procedure? fn))
(error "sequence:for-each : Cannot for-each a non-procedure"))
((not (procedure-of-arity? fn (length sequences)))
(error "sequence:for-each : Cannot for-each procedure -- not of arity" (length sequences)))
((not (apply = (map sequence:size sequences)))
(error "sequence:for-each : Cannot for-each onto sequences of different length"))
(else
(let ((type? (sequence:type (car sequences))))
(if (not (for-all? (cdr sequences) type?))
(error "sequence:for-each : All sequences for for-each must be of the same type"
sequences))
(apply for-each fn
(map sequence:to-list
sequences))))))
(sequence:for-each (apply-display +) '(1 2 3) '(5 5 5))
678
(sequence:for-each (apply-display +) '#(1 2 3) '#(5 5 5))
678
(sequence:for-each (apply-display (select-from-pair char<?))
"abcde"
"ccccc")
abccc
(define (sequence:internal-do-filter sequence predicate)
(sequence:from-list (sequence:type sequence)
(filter predicate
(sequence:to-list sequence))))
(define sequence:filter
(make-generic-operator 2 #f))
(assign-operation sequence:filter sequence:internal-do-filter list? (of-arity? 1))
(assign-operation sequence:filter sequence:internal-do-filter vector? (of-arity? 1))
(assign-operation sequence:filter sequence:internal-do-filter string? (of-arity? 1))
(sequence:filter '(1 2 3 4 5) even?)
(sequence:filter '#(1 2 3 4 5) even?)
(sequence:filter "abcde" (lambda (x) (char>? x #\c)))
(define (list-index lis pred) (let loop ((lis lis) (i 0))
(and (not (null? lis))
(if (pred (car lis))
i
(loop (cdr lis)
(+ 1 i))))))
(define (sequence:internal-do-get-index sequence predicate)
(list-index
(sequence:to-list sequence)
predicate))
(define sequence:get-index
(make-generic-operator 2 #f))
(assign-operation sequence:get-index sequence:internal-do-get-index list? (of-arity? 1))
(assign-operation sequence:get-index sequence:internal-do-get-index vector? (of-arity? 1))
(assign-operation sequence:get-index sequence:internal-do-get-index string? (of-arity? 1))
(sequence:get-index '(1 2 3 4 5) even?)
(sequence:get-index '#(1 2 3 4 5) even?)
(sequence:get-index "abcde" (lambda (x) (char>? x #\c)))
(define (get-element lis pred) (let loop ((lis lis) (i 0))
(and (not (null? lis))
(if (pred (car lis))
(car lis)
(loop (cdr lis)
(+ 1 i))))))
(define (sequence:internal-do-get-element sequence predicate)
(get-element
(sequence:to-list sequence)
predicate))
(define sequence:get-element
(make-generic-operator 2 #f))
(assign-operation sequence:get-element sequence:internal-do-get-element list? (of-arity? 1))
(assign-operation sequence:get-element sequence:internal-do-get-element vector? (of-arity? 1))
(assign-operation sequence:get-element sequence:internal-do-get-element string? (of-arity? 1))
(sequence:get-element '(1 2 3 4 5) even?)
(sequence:get-element '#(1 2 3 4 5) even?)
(sequence:get-element "abcde" (lambda (x) (char>? x #\c)))
(define (sequence:internal-do-fold-right kons seed sequence)
(fold-right
kons
seed
(sequence:to-list sequence)))
(define sequence:fold-right
(make-generic-operator 3 #f))
(assign-operation sequence:fold-right
sequence:internal-do-fold-right
(of-arity? 2)
any?
list?)
(assign-operation sequence:fold-right
sequence:internal-do-fold-right
(of-arity? 2)
any?
vector?)
(assign-operation sequence:fold-right
sequence:internal-do-fold-right
(of-arity? 2)
any?
string?)
(sequence:fold-right * 1 '(1 2 3 4 5))
(sequence:fold-right / 1 '(1 2 3 4 5))
(sequence:fold-right cons '() '#(1 2 3 4 5))
(sequence:fold-right cons '() "abcde")
(define (sequence:internal-do-fold-left kons seed sequence)
(fold-left
kons
seed
(sequence:to-list sequence)))
(define sequence:fold-left
(make-generic-operator 3 #f))
(assign-operation sequence:fold-left
sequence:internal-do-fold-left
(of-arity? 2)
any?
list?)
(assign-operation sequence:fold-left
sequence:internal-do-fold-left
(of-arity? 2)
any?
vector?)
(assign-operation sequence:fold-left
sequence:internal-do-fold-left
(of-arity? 2)
any?
string?)
(sequence:fold-left * 1 '(1 2 3 4 5))
(sequence:fold-left / 1 '(1 2 3 4 5))
(sequence:fold-left cons '() '#(1 2 3 4 5))
(sequence:fold-left cons '() "abcde")
(define (sequence:mixed-append type? . sequences)
(if (null? sequences)
(error "Need at least one sequence for append"))
(fold-right generic:binary-append
(sequence:null type?)
(map (sequence:coercer type?)
sequences)))
(sequence:mixed-append
list?
'(1 2 3)
'#(4 5 6)
"abc")
(sequence:mixed-append
vector?
'#(4 5 6)
"abc"
'(1 2 3))
(sequence:mixed-append
string?
"abc"
'(#\1 #\2 #\3)
'#(#\4 #\5 #\6))
(define (sequence:mixed-map type? fn . sequences)
(cond ((null? sequences)
(error "sequence:map : Need at least one sequence for map"))
((not (procedure? fn))
(error "sequence:map : Cannot map a non-procedure"))
((not (procedure-of-arity? fn (length sequences)))
(error "sequence:map : Cannot map procedure -- not of arity" (length sequences)))
((not (apply = (map sequence:size sequences)))
(error "sequence:map : Cannot map onto sequences of different length"))
(else
(sequence:from-list type?
(apply map fn
(map sequence:to-list
sequences))))))
(sequence:mixed-map vector? + '(1 2 3)
'#(5 5 5))
(define (fold-right kons seed lis-1 . lists)
(if (not (pair? lists))
(let loop ((lis lis-1))
(if (null? lis)
seed
(kons (car lis)
(loop (cdr lis)))))
(let ((lists (cons lis-1 lists)))
(cond ((not (procedure-of-arity? kons (+ 1 (length lists))))
(error "fold:right: procedure not of arity" (length lists)))
(else
(let loop ((lists lists))
(if (there-exists? lists null?)
seed
(let ((cars (map car lists))
(cdrs (map cdr lists)))
(apply kons
(reverse (cons (loop cdrs)
(reverse cars))))))))))))
(define (fold-left kons seed lis-1 . lists)
(if (not (pair? lists))
(let loop ((lis lis-1))
(if (null? lis)
seed
(kons (car lis)
(loop (cdr lis)))))
(let ((lists (cons lis-1 lists)))
(cond ((not (procedure-of-arity? kons (+ 1 (length lists))))
(error "fold:right: procedure not of arity" (length lists)))
(else
(let loop ((lists lists)
(value seed))
(if (there-exists? lists null?)
value
(let ((cars (map car lists))
(cdrs (map cdr lists)))
(loop cdrs
(apply kons (reverse (cons value
(reverse cars)))))))))))))
(fold-right cons* '(z) '(a b c d) '(e e e e e e e e e))
(fold-right + 0 '(1 2 3) '(5 5 5 5))
(fold-left cons* '(z) '(a b c d) '(e e e e e e e e e))
(fold-left + 0 '(1 2 3) '(5 5 5))
(define (sequence:mixed-fold-right kons seed sequence-1 . sequences)
(if (null? sequences)
(sequence:fold-right kons seed sequence-1)
(apply fold-right
kons
seed
(sequence:coerce list? sequence-1)
(map (sequence:coercer list?)
sequences))))
(define (sequence:mixed-fold-left kons seed sequence-1 . sequences)
(if (null? sequences)
(sequence:fold-left kons seed sequence-1)
(apply fold-left
kons
seed
(sequence:coerce list? sequence-1)
(map (sequence:coercer list?)
sequences))))
(sequence:mixed-fold-right + 0 '(1 2 3) '#(5 5 5 5))
(sequence:mixed-fold-right
(lambda (x y z)
(generic:binary-append
(apply sequence:construct string? (make-list x y))
z))
(sequence:null string?)
'(1 2 3)
"abc")
(sequence:mixed-fold-left
(lambda (x y z)
(generic:binary-append
(apply sequence:construct string? (make-list x y))
z))
(sequence:null string?)
'(1 2 3)
"abc")
(define (string-chop string n)
(if (negative? n)
(string-tail string (- n))
(string-head string
(- (string-length string)
n))))
(string-chop "foo bar baz" 3)
(string-chop "foo bar baz" -3)
(define (reverse-arguments f)
(lambda args
(apply f (reverse args))))
((reverse-arguments -) 1 5)
(define (remove-all x lis)
(let loop ((lis lis))
(cond ((null? lis)
'())
((eqv? x (car lis))
(loop (cdr lis)))
(else
(cons (car lis)
(loop (cdr lis)))))))
(define +bin (make-generic-operator 2 +))
(define -bin (make-generic-operator 2 -))
(define *bin (make-generic-operator 2 *))
(define /bin (make-generic-operator 2 /))
(assign-operation +bin
(reverse-arguments cons)
list?
any?)
(assign-operation +bin
(lambda (x y)
(vector-map + x y))
vector?
vector?)
(assign-operation +bin
(lambda (x y)
(vector-map (lambda (z) (+ y z))
x))
vector?
number?)
(assign-operation +bin
(lambda (y x)
(vector-map (lambda (z) (+ y z))
x))
number?
vector?)
(assign-operation +bin string-append string? string?)
(assign-operation -bin
(reverse-arguments remove-all)
list?
any?)
(assign-operation -bin
(lambda (x y)
(vector-map - x y))
vector?
vector?)
(assign-operation -bin
(lambda (x y)
(vector-map (lambda (z) (- y z))
x))
vector?
number?)
(assign-operation -bin
(lambda (y x)
(vector-map (lambda (z) (- z y))
x))
number?
vector?)
(assign-operation -bin string-chop string? exact-integer?)
(assign-operation *bin
(reverse-arguments make-list)
list?
exact-integer?)
(assign-operation *bin
dot-product
vector?
vector?)
(assign-operation *bin
(lambda (x y)
(vector-map (lambda (z) (* y z))
x))
vector?
number?)
(assign-operation *bin
(lambda (y x)
(vector-map (lambda (z) (* y z))
x))
number?
vector?)
(assign-operation *bin
(lambda (string n)
(apply string-append
(make-list n string)))
string?
exact-integer?)
(assign-operation /bin
(lambda (x y)
(vector-map (lambda (z) (/ z y))
x))
vector?
number?)
(assign-operation /bin
(lambda (y x)
(vector-map (lambda (z) (/ y z))
x))
number?
vector?)
(define generic-arithmetic-environment
(extend-top-level-environment user-initial-environment))
(define ref-env (the-environment))
(environment-define generic-arithmetic-environment '+ +bin)
(environment-define generic-arithmetic-environment '- -bin)
(environment-define generic-arithmetic-environment '* *bin)
(environment-define generic-arithmetic-environment '/ /bin)
(environment-define generic-arithmetic-environment 'old-env ref-env)
(ge generic-arithmetic-environment)
(+ '(a b c)
'z)
(+ '#(1 2 3)
'#(5 5 5))
(+ '#(1 2 3)
5)
(+ 5
'#(1 2 3))
(+ "foo "
"bar")
(- '(a x b x c)
'x)
(- '#(5 5 5)
'#(1 2 3))
(- '#(1 2 3)
5)
(- 5
'#(1 2 3))
(- "foo bar baz"
4)
(- "foo bar baz"
-4)
(* '(a b c)
3)
(* '#(5 5 5)
'#(1 2 3))
(* 5
'#(1 2 3))
(* '#(1 2 3)
5)
(/ '#(5 10 15)
5)
(/ 6
'#(1 2 3))