📄 streams.scm
字号:
;;;; streams.scm --- general lazy streams;;;; -*- Scheme -*-;;;; Copyright (C) 1999, 2001 Free Software Foundation, Inc.;;;; ;;;; This program is free software; you can redistribute it and/or modify;;;; it under the terms of the GNU General Public License as published by;;;; the Free Software Foundation; either version 2, or (at your option);;;; any later version.;;;; ;;;; This program is distributed in the hope that it will be useful,;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the;;;; GNU General Public License for more details.;;;; ;;;; You should have received a copy of the GNU General Public License;;;; along with this software; see the file COPYING. If not, write to;;;; the Free Software Foundation, Inc., 59 Temple Place, Suite 330,;;;; Boston, MA 02111-1307 USA;;;;;;;; As a special exception, the Free Software Foundation gives permission;;;; for additional uses of the text contained in its release of GUILE.;;;;;;;; The exception is that, if you link the GUILE library with other files;;;; to produce an executable, this does not by itself cause the;;;; resulting executable to be covered by the GNU General Public License.;;;; Your use of that executable is in no way restricted on account of;;;; linking the GUILE library code into it.;;;;;;;; This exception does not however invalidate any other reasons why;;;; the executable file might be covered by the GNU General Public License.;;;;;;;; This exception applies only to the code released by the;;;; Free Software Foundation under the name GUILE. If you copy;;;; code from other Free Software Foundation releases into a copy of;;;; GUILE, as the General Public License permits, the exception does;;;; not apply to the code that you add in this way. To avoid misleading;;;; anyone as to the status of such modified files, you must delete;;;; this exception notice from them.;;;;;;;; If you write modifications of your own for GUILE, it is your choice;;;; whether to permit this exception to apply to your modifications.;;;; If you do not wish that, delete this exception notice.;; the basic stream operations are inspired by;; (i.e. ripped off) Scheme48's `stream' package,;; modulo stream-empty? -> stream-null? renaming.(define-module (ice-9 streams) :export (make-stream stream-car stream-cdr stream-null? list->stream vector->stream port->stream stream->list stream->reversed-list stream->list&length stream->reversed-list&length stream->vector stream-fold stream-for-each stream-map));; Use:;;;; (make-stream producer initial-state);; - PRODUCER is a function of one argument, the current state.;; it should return either a pair or an atom (i.e. anything that;; is not a pair). if PRODUCER returns a pair, then the car of the pair;; is the stream's head value, and the cdr is the state to be fed;; to PRODUCER later. if PRODUCER returns an atom, then the stream is;; considered depleted.;;;; (stream-car stream);; (stream-cdr stream);; (stream-null? stream);; - yes.;;;; (list->stream list);; (vector->stream vector);; - make a stream with the same contents as LIST/VECTOR.;;;; (port->stream port read);; - makes a stream of values which are obtained by READing from PORT.;;;; (stream->list stream);; - returns a list with the same contents as STREAM.;;;; (stream->reversed-list stream);; - as above, except the contents are in reversed order.;;;; (stream->list&length stream);; (stream->reversed-list&length stream);; - multiple-valued versions of the above two, the second value is the;; length of the resulting list (so you get it for free).;;;; (stream->vector stream);; - yes.;;;; (stream-fold proc init stream0 ...);; - PROC must take (+ 1 <number-of-stream-arguments>) arguments, like this:;; (PROC car0 ... init). *NOTE*: the INIT argument is last, not first.;; I don't have any preference either way, but it's consistent with;; `fold[lr]' procedures from SRFI-1. PROC is applied to successive;; elements of the given STREAM(s) and to the value of the previous;; invocation (INIT on the first invocation). the last result from PROC;; is returned.;;;; (stream-for-each proc stream0 ...);; - like `for-each' we all know and love.;;;; (stream-map proc stream0 ...);; - like `map', except returns a stream of results, and not a list.;; Code:(define (make-stream m state) (delay (let ((o (m state))) (if (pair? o) (cons (car o) (make-stream m (cdr o))) '()))))(define (stream-car stream) "Returns the first element in STREAM. This is equivalent to `car'." (car (force stream)))(define (stream-cdr stream) "Returns the first tail of STREAM. Equivalent to `(force (cdr STREAM))'." (cdr (force stream)))(define (stream-null? stream) "Returns `#t' if STREAM is the end-of-stream marker; otherwisereturns `#f'. This is equivalent to `null?', but should be usedwhenever testing for the end of a stream." (null? (force stream)))(define (list->stream l) "Returns a newly allocated stream whose elements are the elements ofLIST. Equivalent to `(apply stream LIST)'." (make-stream (lambda (l) l) l))(define (vector->stream v) (make-stream (let ((len (vector-length v))) (lambda (i) (or (= i len) (cons (vector-ref v i) (+ 1 i))))) 0))(define (stream->reversed-list&length stream) (let loop ((s stream) (acc '()) (len 0)) (if (stream-null? s) (values acc len) (loop (stream-cdr s) (cons (stream-car s) acc) (+ 1 len)))))(define (stream->reversed-list stream) (call-with-values (lambda () (stream->reversed-list&length stream)) (lambda (l len) l)))(define (stream->list&length stream) (call-with-values (lambda () (stream->reversed-list&length stream)) (lambda (l len) (values (reverse! l) len))))(define (stream->list stream) "Returns a newly allocated list whose elements are the elements of STREAM.If STREAM has infinite length this procedure will not terminate." (reverse! (stream->reversed-list stream)))(define (stream->vector stream) (call-with-values (lambda () (stream->reversed-list&length stream)) (lambda (l len) (let ((v (make-vector len))) (let loop ((i 0) (l l)) (if (not (null? l)) (begin (vector-set! v (- len i 1) (car l)) (loop (+ 1 i) (cdr l))))) v))))(define (stream-fold f init stream . rest) (if (null? rest) ;fast path (stream-fold-one f init stream) (stream-fold-many f init (cons stream rest))))(define (stream-fold-one f r stream) (if (stream-null? stream) r (stream-fold-one f (f (stream-car stream) r) (stream-cdr stream))))(define (stream-fold-many f r streams) (if (or-map stream-null? streams) r (stream-fold-many f (apply f (let recur ((cars (map stream-car streams))) (if (null? cars) (list r) (cons (car cars) (recur (cdr cars)))))) (map stream-cdr streams))))(define (stream-for-each f stream . rest) (if (null? rest) ;fast path (stream-for-each-one f stream) (stream-for-each-many f (cons stream rest))))(define (stream-for-each-one f stream) (if (not (stream-null? stream)) (begin (f (stream-car stream)) (stream-for-each-one f (stream-cdr stream)))))(define (stream-for-each-many f streams) (if (not (or-map stream-null? streams)) (begin (apply f (map stream-car streams)) (stream-for-each-one f (map stream-cdr streams)))))(define (stream-map f stream . rest) "Returns a newly allocated stream, each element being the result ofinvoking F with the corresponding elements of the STREAMsas its arguments." (if (null? rest) ;fast path (make-stream (lambda (s) (or (stream-null? s) (cons (f (stream-car s)) (stream-cdr s)))) stream) (make-stream (lambda (streams) (or (or-map stream-null? streams) (cons (apply f (map stream-car streams)) (map stream-cdr streams)))) (cons stream rest))))(define (port->stream port read) (make-stream (lambda (p) (let ((o (read p))) (or (eof-object? o) (cons o p)))) port));;; streams.scm ends here
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -