examples/streams.scm

Summary

Maintainability
Test Coverage
;; Example streams
;;
;; Reference:
;; http://people.cs.aau.dk/~normark/prog3-03/html/notes/eval-order_themes-delay-stream-section.html
;;
;; This file is part of the LIPS - Scheme based Powerful lisp in JavaScript
;; Copyright (C) 2019-2024 Jakub T. Jankiewicz <https://jcubic.pl/me>
;; Released under MIT license
;;

(define-macro (stream-cons x y)
  `(cons ,x (delay ,y)))

;; -----------------------------------------------------------------------------
(define (stream-car stream)
  (car stream))

;; -----------------------------------------------------------------------------
(define (stream-cdr stream)
  (force (cdr stream)))

;; -----------------------------------------------------------------------------
(define head stream-car)
(define tail stream-cdr)

;; -----------------------------------------------------------------------------
(define (empty-stream? x) (eq? x the-empty-stream))

;; -----------------------------------------------------------------------------
(define the-empty-stream '())

;; -----------------------------------------------------------------------------
(define (stream-take n stream)
  (if (<= n 0)
      '()
      (cons (head stream) (stream-take (- n 1) (tail stream)))))

;; -----------------------------------------------------------------------------
(define (stream-section n stream)
  (cond ((= n 0) '())
        (else
         (cons
          (head stream)
          (stream-section
           (- n 1)
           (tail stream))))))

;; --------------------------------------------------------------------------
(define (stream-inject init fn stream)
  (let iter ((result init)
             (stream stream))
    (if (empty-stream? (stream-cdr stream))
        result
        (iter (fn result (stream-car stream))
              (stream-cdr stream)))))

;; -----------------------------------------------------------------------------
(define (stream-add s1 s2)
  (let ((h1 (head s1))
        (h2 (head s2)))
    (stream-cons
     (+ h1 h2)
     (stream-add (tail s1) (tail s2)))))

;; --------------------------------------------------------------------------
(define (stream-range n)
  (let loop ((i 0))
    (if (= i n)
        the-empty-stream
        (stream-cons i (loop (+ i 1))))))
;; --------------------------------------------------------------------------
(define (stream-reduce fun stream)
  (let iter ((result (stream-car stream))
             (stream (stream-cdr stream)))
    (if (empty-stream? stream)
        result
        (iter (fun result (stream-car stream))
              (stream-cdr stream)))))

;; -----------------------------------------------------------------------------
(define (stream-zip . streams)
  (if (empty-stream? streams)
      the-empty-stream
      (stream-cons (apply list (map stream-car streams))
                   (apply stream-zip (map stream-cdr streams)))))

;; --------------------------------------------------------------------------
(define (stream-map proc . streams)
  (define (single-map proc stream)
    (if (empty-stream? stream)
        the-empty-stream
        (stream-cons (apply proc (stream-car stream))
                     (single-map proc (stream-cdr stream)))))
  (single-map proc (apply zip-streams streams)))

;; --------------------------------------------------------------------------
(define (stream-for-each proc stream)
  (unless (empty-stream? stream)
    (proc (stream-car stream))
    (stream-for-each proc (stream-cdr stream))))

;; --------------------------------------------------------------------------
(define (stream-limit n stream)
  "return stream of n elements of stream <stream> ( -> stream = {0 .. n})"
  (let iter ((n n) (stream stream))
    (if (or (empty-stream? stream) (eq? n 0))
        the-empty-stream
        (stream-cons (stream-car stream)
                     (iter (- n 1)
                           (stream-cdr stream))))))

;; -----------------------------------------------------------------------------
(define (stream-slice a b stream)
  (let loop ((n (- b a)) (stream (skip-stream a stream)))
    (if (eq? n 0)
        the-empty-stream
        (stream-cons (stream-car stream)
                     (loop (- n 1) (stream-cdr stream))))))

;; -----------------------------------------------------------------------------
(define (stream-force stream)
  (let iter ((stream stream))
    (if (empty-stream? stream)
        '()
        (cons (stream-car stream)
              (iter (stream-cdr stream))))))

;; -----------------------------------------------------------------------------
;; example streams
;; -----------------------------------------------------------------------------
(define fibs
  (stream-cons 0
               (stream-cons 1
                            (add-streams (tail fibs) fibs))))

;; -----------------------------------------------------------------------------
(define (integers-from n)
  (stream-cons n (integers-from (+ n 1))))

;; -----------------------------------------------------------------------------
(define ones (stream-cons 1 ones))

;; -----------------------------------------------------------------------------
(define integers (stream-cons 1 (add-streams integers ones)))

;; -----------------------------------------------------------------------------
(define (! n)
  (stream-reduce * (stream-limit n integers)))

;; -----------------------------------------------------------------------------
(define factorials
  (stream-map ! integers))

;; -----------------------------------------------------------------------------
(define (divisible? x y)
  (eq? (gcd x y) y))

;; -----------------------------------------------------------------------------
(define (sieve stream)
  (stream-cons
   (stream-car stream)
   (sieve (stream-filter
           (lambda (x)
             (not
              (divisible? x (stream-car stream))))
           (stream-cdr stream)))))

;; -----------------------------------------------------------------------------
(define (stream-scale stream n)
  (stream-map (lambda (x) (* x n)) stream))

;;(stream-force (limit 10 (stream-map (lambda (a b) (+ a b)) integers (stream-cdr integers))))