chickadee » transducers » define-interleave-transducer

(define-interleave-transducer name make-state done? next update)syntax
(define-zip-transducer name make-state done? next update)syntax

A macro that defines an interleave / zip transducer for a specific type given four procedures. The procedures are as follows:

 
;; Defined as follows:

(define-syntax define-interleave-transducer
  (syntax-rules ()
    ((_ name make-state done? next update)
     (define (name collection)
       (lambda (reducer)
         (let ((state (make-state collection)))
           (case-lambda
             (() (reducer))
             ((result) (reducer result))
             ((result item)
              (if (done? collection state)
                (make-reduced result)
                (let ((interleave-item (next collection state))
                      (next-result (reducer result item)))
                  (set! state (update collection state))
                  (if (reduced? next-result)
                    next-result
                    (reducer next-result interleave-item))))))))))))

(define-syntax define-zip-transducer
  (syntax-rules ()
    ((_ name make-state done? next update)
     (define (name collection)
       (lambda (reducer)
         (let ((state (make-state collection)))
           (case-lambda
             (() (reducer))
             ((result) (reducer result))
             ((result item)
              (if (done? collection state)
                (make-reduced result)
                (let ((zip-item (next collection state)))
                  (set! state (update collection state))
                  (reducer result (cons item zip-item))))))))))))
  • make-state: a procedure that takes in the initial collection to interleave and creates a state for the interleave process. For lists this could just be the list, for vectors this might just be an index counter. See the following examples.
  • done?: a predicate that takes in the initial collection and the interleave state and returns #t iff the interleave process should stop (e.g. if a list is exhausted, or a vector exhausted).
  • next: a procedure that takes in the initial collection and the interleave state and returns the next item to be interleaved into the transduced sequence.
  • update: a procedure that takes in the initial collection and the interleave state and returns an updated state.

Note that these procedures should be the same for both interleave and zip transducers. Some examples that are already included in the egg:

 
(define-interleave-transducer interleave-list
    (lambda (coll) coll)
    (lambda (_ s) (null? s))
    (lambda (_ s) (car s))
    (lambda (_ s) (cdr s)))

(define-interleave-transducer interleave-vector
    (lambda (coll) 0)
    (lambda (coll s) (fx>= s (vector-length coll)))
    vector-ref
    (lambda (_ s) (fx+ s 1)))

Generally speaking, how to implement these can be somewhat difficult to understand without the above macro definitions. The macro is more a convenience, and the various interleave and zip transducers can be implemented without the above syntax.