./lisp/scheme/test/streams.sc

download original
;--------interface------------

;; primitives:

; empty-stream
; (stream-empty? s)
; (make-stream head tail-stream)
; (stream-head s)
; (stream-tail s)

; axioms:

;  (stream-head (make-stream head tail-stream)) == head
;  (stream-tail (make-stream head tail-stream)) == tail-stream
;  (stream-head empty-stream) == <undefined>
;  (stream-tail empty-stream) == <undefined>
;  (stream-empty? empty-stream) == #t
;  (stream-empty? (make-stream head tail-stream)) == #f



; utilities:

; (take-first n s)   => stream
; (stream-map mapping-proc s)   => stream
; (stream-accumulate combiner-proc startval s)  => object (return value of proc)
; (stream-filter filter-proc s)  => stream


; various constructors:

; (make-loop-stream startval incrementor continue-pred)
; (make-int-interval-stream start stop)  ; if (null? stop): infinite stream starting at start


;--------representation-------

; - uses "lazy evaluation":

; - the empty stream is '()

; - a nonempty stream is a cons whose car is the stream's head, and whose cdr is a
;     procedure of 0 arguments that returns the stream's tail (which is again a stream)

;(use-syntax (ice-9 syncase))   ; for Guile

;helpers (Scheme doesn't define them)
(define (1+ x) (+ x 1))
(define (1- x) (- x 1))

(define empty-stream '())

(define stream-empty? null?)

(define-syntax make-stream
  (syntax-rules ()
                ((make-stream head tail)
                 (cons head (delay tail)))))

;(define-syntax make-stream
;  (syntax-rules ()
;                ((make-stream head tail)
;                 (cons head (lambda () tail)))))


(define stream-head car)

(define (stream-tail s)
  (force (cdr s)))

;(define (stream-tail s)
;  ((cdr s)))


;;TODO: tail recursiveness

(define (take-first n s)
  (cond ((<= n 0) empty-stream)
        ((stream-empty? s) empty-stream)
        (else
         (make-stream
          (stream-head s)
          (take-first (1- n) (stream-tail s))))))


(define (take-nth n s)
  (if (= n 0)
      (stream-head s)
      (take-nth (1- n) (stream-tail s))))

(define (stream-map mapping-proc s)
  (if (stream-empty? s)
      empty-stream
      (make-stream (mapping-proc (stream-head s))
                   (stream-map mapping-proc (stream-tail s)))))

;; don't use for infinite streams...
(define (stream-accumulate combiner-proc startval s)
  (if (stream-empty? s)
      startval
      (stream-accumulate combiner-proc
                         (combiner-proc startval (stream-head s))
                         (stream-tail s))))

;; don't use for infinite streams...
(define (stream-to-list s)
  (stream-accumulate (lambda (x y) (cons y x)) '() s))


(define (stream-length s)
  (stream-accumulate (lambda (curr-length obj) (1+ curr-length)) 0 s))

(define (stream-filter filter-proc s)
  (if (stream-empty? s)
      empty-stream
      (let ((h (filter-proc (stream-head s))))
        (if h
            (make-stream (stream-head s) (stream-filter filter-proc
                                                        (stream-tail s)))
            (stream-filter filter-proc
                           (stream-tail s))))))


(define (stream-append s1 s2)
  (if (stream-empty? s1)
      s2
      (make-stream (stream-head s1)
                   (stream-append (stream-tail s1)
                                  s2))))


(define (stream-flatten1 s)
  (stream-accumulate stream-append empty-stream s))


(define (make-loop-stream startval incrementor continue-pred)
  (if (not (continue-pred startval))
      empty-stream
      (make-stream
       startval
       (make-loop-stream (incrementor startval) incrementor continue-pred))))

(define (make-int-interval-stream start stop)
  (make-loop-stream start
                    1+
                    (lambda (x) (or (null? stop)
                                    (<= x stop)))))


; all natural numbers (infinite stream)
(define naturals-stream
  (make-int-interval-stream 0 '()))

  
back to test

(C) 1998-2017 Olaf Klischat <olaf.klischat@gmail.com>