diff options
Diffstat (limited to 'collect.scm')
-rw-r--r-- | collect.scm | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/collect.scm b/collect.scm new file mode 100644 index 0000000..abdf209 --- /dev/null +++ b/collect.scm @@ -0,0 +1,236 @@ +;"collect.scm" Sample collection operations +; COPYRIGHT (c) Kenneth Dickey 1992 +; +; This software may be used for any purpose whatever +; without warrantee of any kind. +; AUTHOR Ken Dickey +; DATE 1992 September 1 +; LAST UPDATED 1992 September 2 +; NOTES Expository (optimizations & checks elided). +; Requires YASOS (Yet Another Scheme Object System). + +(require 'yasos) + +(define-operation (collect:collection? obj) + ;; default + (cond + ((or (list? obj) (vector? obj) (string? obj)) #t) + (else #f) +) ) + +(define (collect:empty? collection) (zero? (yasos:size collection))) + +(define-operation (collect:gen-elts <collection>) ;; return element generator + ;; default behavior + (cond ;; see utilities, below, for generators + ((vector? <collection>) (collect:vector-gen-elts <collection>)) + ((list? <collection>) (collect:list-gen-elts <collection>)) + ((string? <collection>) (collect:string-gen-elts <collection>)) + (else + (slib:error "Operation not supported: GEN-ELTS " (yasos:print obj #f))) +) ) + +(define-operation (collect:gen-keys collection) + (if (or (vector? collection) (list? collection) (string? collection)) + (let ( (max+1 (yasos:size collection)) (index 0) ) + (lambda () + (cond + ((< index max+1) + (set! index (collect:add1 index)) + (collect:sub1 index)) + (else (slib:error "no more keys in generator")) + ) ) ) + (slib:error "Operation not handled: GEN-KEYS " collection) +) ) + +(define (collect:do-elts <proc> . <collections>) + (let ( (max+1 (yasos:size (car <collections>))) + (generators (map collect:gen-elts <collections>)) + ) + (let loop ( (counter 0) ) + (cond + ((< counter max+1) + (apply <proc> (map (lambda (g) (g)) generators)) + (loop (collect:add1 counter)) + ) + (else 'unspecific) ; done + ) ) +) ) + +(define (collect:do-keys <proc> . <collections>) + (let ( (max+1 (yasos:size (car <collections>))) + (generators (map collect:gen-keys <collections>)) + ) + (let loop ( (counter 0) ) + (cond + ((< counter max+1) + (apply <proc> (map (lambda (g) (g)) generators)) + (loop (collect:add1 counter)) + ) + (else 'unspecific) ; done + ) ) +) ) + +(define (collect:map-elts <proc> . <collections>) + (let ( (max+1 (yasos:size (car <collections>))) + (generators (map collect:gen-elts <collections>)) + (vec (make-vector (yasos:size (car <collections>)))) + ) + (let loop ( (index 0) ) + (cond + ((< index max+1) + (vector-set! vec index (apply <proc> (map (lambda (g) (g)) generators))) + (loop (collect:add1 index)) + ) + (else vec) ; done + ) ) +) ) + +(define (collect:map-keys <proc> . <collections>) + (let ( (max+1 (yasos:size (car <collections>))) + (generators (map collect:gen-keys <collections>)) + (vec (make-vector (yasos:size (car <collections>)))) + ) + (let loop ( (index 0) ) + (cond + ((< index max+1) + (vector-set! vec index (apply <proc> (map (lambda (g) (g)) generators))) + (loop (collect:add1 index)) + ) + (else vec) ; done + ) ) +) ) + +(define-operation (collect:for-each-key <collection> <proc>) + ;; default + (collect:do-keys <proc> <collection>) ;; talk about lazy! +) + +(define-operation (collect:for-each-elt <collection> <proc>) + (collect:do-elts <proc> <collection>) +) + +(define (collect:reduce <proc> <seed> . <collections>) + (let ( (max+1 (yasos:size (car <collections>))) + (generators (map collect:gen-elts <collections>)) + ) + (let loop ( (count 0) ) + (cond + ((< count max+1) + (set! <seed> + (apply <proc> <seed> (map (lambda (g) (g)) generators))) + (loop (collect:add1 count)) + ) + (else <seed>) + ) ) +) ) + + + +;; pred true for every elt? +(define (collect:every? <pred?> . <collections>) + (let ( (max+1 (yasos:size (car <collections>))) + (generators (map collect:gen-elts <collections>)) + ) + (let loop ( (count 0) ) + (cond + ((< count max+1) + (if (apply <pred?> (map (lambda (g) (g)) generators)) + (loop (collect:add1 count)) + #f) + ) + (else #t) + ) ) +) ) + +;; pred true for any elt? +(define (collect:any? <pred?> . <collections>) + (let ( (max+1 (yasos:size (car <collections>))) + (generators (map collect:gen-elts <collections>)) + ) + (let loop ( (count 0) ) + (cond + ((< count max+1) + (if (apply <pred?> (map (lambda (g) (g)) generators)) + #t + (loop (collect:add1 count)) + )) + (else #f) + ) ) +) ) + + +;; MISC UTILITIES + +(define (collect:add1 obj) (+ obj 1)) +(define (collect:sub1 obj) (- obj 1)) + +;; Nota Bene: list-set! is bogus for element 0 + +(define (collect:list-set! <list> <index> <value>) + + (define (set-loop last this idx) + (cond + ((zero? idx) + (set-cdr! last (cons <value> (cdr this))) + <list> + ) + (else (set-loop (cdr last) (cdr this) (collect:sub1 idx))) + ) ) + + ;; main + (if (zero? <index>) + (cons <value> (cdr <list>)) ;; return value + (set-loop <list> (cdr <list>) (collect:sub1 <index>))) +) + +(add-setter list-ref collect:list-set!) ; for (setter list-ref) + + +;; generator for list elements +(define (collect:list-gen-elts <list>) + (lambda () + (if (null? <list>) + (slib:error "No more list elements in generator") + (let ( (elt (car <list>)) ) + (set! <list> (cdr <list>)) + elt)) +) ) + +;; generator for vector elements +(define (collect:make-vec-gen-elts <accessor>) + (lambda (vec) + (let ( (max+1 (yasos:size vec)) + (index 0) + ) + (lambda () + (cond ((< index max+1) + (set! index (collect:add1 index)) + (<accessor> vec (collect:sub1 index)) + ) + (else #f) + ) ) + ) ) +) + +(define collect:vector-gen-elts (collect:make-vec-gen-elts vector-ref)) + +(define collect:string-gen-elts (collect:make-vec-gen-elts string-ref)) + +;;; exports: + +(define collection? collect:collection?) +(define empty? collect:empty?) +(define gen-keys collect:gen-keys) +(define gen-elts collect:gen-elts) +(define do-elts collect:do-elts) +(define do-keys collect:do-keys) +(define map-elts collect:map-elts) +(define map-keys collect:map-keys) +(define for-each-key collect:for-each-key) +(define for-each-elt collect:for-each-elt) +(define reduce collect:reduce) ; reduce is also in comlist.scm +(define every? collect:every?) +(define any? collect:any?) + +;; --- E O F "collect.oo" --- ;; |