;;; CHICKEN Transducers - Transducers for working with foldable data types. ;;; ;;; Copyright (c) 2023 Jeremy Steward ;;; ;;; Permission is hereby granted, free of charge, to any person obtaining a copy ;;; of this software and associated documentation files (the "Software"), to deal ;;; in the Software without restriction, including without limitation the rights ;;; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ;;; copies of the Software, and to permit persons to whom the Software is ;;; furnished to do so, subject to the following conditions: ;;; ;;; The above copyright notice and this permission notice shall be included in all ;;; copies or substantial portions of the Software. ;;; ;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ;;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ;;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ;;; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ;;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ;;; SOFTWARE. (define-library (transducers ports) (import (scheme base) (scheme case-lambda) (transducers base)) (cond-expand (chicken-5 (import (only (chicken base) void) (only (check-errors) define-check+error-type check-procedure))) (else (error "Transducers does not yet support this R7RS Scheme implementation."))) (include-library-declarations "src/transducers.ports.exports.scm") (begin ;; A reducer that aggregates the transduction into a new list in the order of ;; the items reduced. (define collect-writer (case-lambda ((writer) (collect-writer writer (void))) ((writer sentinel) (case-lambda (() (void)) ((result) result) ((result item) (writer item)))))) ;; Transducer-aware folding operation over ports given a reader procedure. ;; ;; This procedure takes in a reducer `f`, a `sentinel` value for that ;; reducer, and a reader `reader` to call `(f sentinel x)` on repeatedly, ;; taking the result of the reducer as the new sentinel value each time. (define (reader-fold f sentinel reader) (check-procedure 'reader-fold reader 'reader) (let loop ((collector sentinel) (x (reader))) (if (eof-object? x) collector (let ((result (f collector x))) (if (reduced? result) (unwrap result) (loop result (reader))))))) ;; A transducer that chains another reader onto the current transduction (define-chain-transducer chain-reader reader-fold) ;; A transducer that interleaves the contents of a list (define-interleave-transducer interleave-reader (lambda (reader) (reader)) (lambda (_ s) (eof-object? s)) (lambda (_ s) s) (lambda (reader _) (reader))) ;; A transducer that zips the contents of a list (define-zip-transducer zip-reader (lambda (reader) (reader)) (lambda (_ s) (eof-object? s)) (lambda (_ s) s) (lambda (reader _) (reader)))) ;; End-of-module )