;;; Project: Scheme-PG ;;; Author: David J. Neu, djneu@acm.org ;;; Maintainer: David J. Neu, djneu@acm.org ;;; Project Home Page: http://scheme-pg.sourceforge.net ;;; Copyright: Copyright (c) 2004 Universal Technical Resource Services, Inc. ;;; License: MIT License, see license.txt ;;; CVS Id: $Id: stream.ss,v 1.1.1.1 2004/09/03 20:22:15 djneu Exp $ (module stream mzscheme (require "cursor.ss") ;(require (lib "defmacro.ss")) ;;; Didn't use the build-in delay and force because don't want values ;;; to be cached. (define-syntax stream-delay (syntax-rules () ((_ expr) (lambda () expr)))) ;;; A define-macro, non-hygienic macros version of stream-delay. ; (define-macro stream-delay ; (lambda (expr) ; `(lambda () ,expr))) (define stream-force (lambda (apromise) (apromise))) ;;; Returns a pair with the car being a value and the cdr being a ;;; promise that when forced returns the next pair in the stream. (define-syntax stream-cons (syntax-rules () ((_ avalue astream) (cons avalue (stream-delay astream))))) ;;;A define-macro, non-hygienic macros version of stream-cons. ;(define-macro stream-cons ; (lambda (avalue astream) ; `(cons ,avalue (stream-delay ,astream)))) ;;; stream-car: stream -> value (define stream-car (lambda (astream) ;(car astream))) (caar astream))) ;;; stream-car: stream -> cursor (define stream-cursor (lambda (astream) ;(car astream))) (cdar astream))) ;;; stream-car: stream -> stream (define stream-cdr (lambda (astream) (stream-force (cdr astream)))) (define null-stream '()) ;;; stream-null?: stream -> boolean (define stream-null? (lambda (astream) (null? astream))) ;;; stream->list: stream -> list ;;; Returns the elements of the stream as a list. (define stream->list (lambda (astream) (if (stream-null? astream) '() (cons (stream-car astream) (stream->list (stream-cdr astream)))))) ;;; stream: connection string symbol -> stream ;;; Creates a cursor and returns a stream that contains it's contents. (define stream (lambda (aconnection aselect aclient/server) (let loop ((lcursor (cursor-open aconnection aselect aclient/server))) (let ((lrow (cursor-next lcursor))) (if (eoc-object? lrow) (begin (cursor-close lcursor) null-stream) ;(stream-cons lrow (loop lcursor))))))) (stream-cons (cons lrow lcursor) (loop lcursor))))))) ;;; stream-ref: stream non-negative-integer -> value (define stream-ref (lambda (astream aindex) (let ((lcursor (stream-cursor astream))) (cursor-ref lcursor aindex)))) ;;; stream-ref!: stream non-negative-integer -> value (define stream-ref! (lambda (astream aindex) (let ((lcursor (stream-cursor astream))) (cursor-ref! lcursor aindex)))) ;;; stream-metadata: stream -> association list (define stream-metadata (lambda (astream aindex) (let ((lcursor (stream-cursor astream))) (cursor-metadata lcursor)))) ;;; stream-length: stream -> non-negative integer ;;; Since all the streams we work with are finite, we can provide the ;;; stream-length function. (define stream-length (lambda (astream aindex) (let ((lcursor (stream-cursor astream))) (cursor-length lcursor)))) (provide stream-delay stream-force stream-cons stream-car stream-cursor stream-cdr null-stream stream-null? stream->list stream stream-ref stream-ref! stream-metadata stream-length))