;; This module produces a sequence that merges streams in order (by <) #lang racket/base (require racket/stream) (define-values (tl-first tl-rest tl-empty?) (values stream-first stream-rest stream-empty?)) (define-struct merged-stream (< ss v ss′) #:mutable ; sadly, so we don't have to redo potentially expensive < #:methods gen:stream [(define (stream-empty? S) ;; andmap defined to be true when ss is null (andmap tl-empty? (merged-stream-ss S))) (define (cache-next-head S) (unless (box? (merged-stream-v S)) (define < (merged-stream-< S)) (define ss (merged-stream-ss S)) (define-values (best-f best-i) (for/fold ((F #f) (I 0)) ((s (in-list ss)) (i (in-naturals))) (if (tl-empty? s) (values F I) (let ((f (tl-first s))) (if (or (not F) (< f (unbox F))) (values (box f) i) (values F I)))))) (set-merged-stream-v! S best-f) (define ss′ (for/list ((s ss) (i (in-naturals)) #:unless (tl-empty? s)) (if (= i best-i) (tl-rest s) s))) (set-merged-stream-ss′! S ss′)) S) (define (stream-first S) (cache-next-head S) (unbox (merged-stream-v S))) (define (stream-rest S) (cache-next-head S) (struct-copy merged-stream S [ss (merged-stream-ss′ S)] [v #f]))]) (define ((merge-sequences <) . sqs) (let ((strms (map sequence->stream sqs))) (merged-stream < strms #f #f))) ;; --------------------------------------------------------------------------------------------------- (module+ main (require racket/string) ;; there are file streams and all sorts of other streams -- we can even read lines from strings (for ((l ((merge-sequences string