sigildocs

(sigil seq)

(sigil seq) - Polymorphic Sequences and Transducers

Unified collection processing that works across lists, vectors, and dicts. Built on transducers for composable, efficient transformations.

Polymorphic Operations

When imported, these shadow the single-type versions from prelude:

(import (sigil seq))

(map square '(1 2 3))     ; => (1 4 9)
(map square #(1 2 3))     ; => #(1 4 9)
(filter even? '(1 2 3 4)) ; => (2 4)
(filter even? #(1 2 3 4)) ; => #(2 4)

Transducers

Transducers are composable transformation pipelines:

(define xform
  (comp (filtering even?)
        (mapping square)
        (taking 5)))

(transduce xform conj '() (iota 100))  ; => (0 4 16 36 64)

Transducers separate the "what" (transformation) from the "how" (iteration), enabling the same transformation to work on any collection type.

Stream Processing with Channels

The same transducers work for processing channel message streams:

(import (sigil seq)
        (sigil channels)
        (sigil async))

(define log-xform
  (comp (filtering (lambda (msg) (equal? (dict-ref msg level:) "error")))
        (mapping (lambda (msg) (dict-ref msg text:)))))

(with-async
  ;; Producer: send log messages
  (go (for-each (lambda (msg) (channel-send logs msg))
                messages)
      (channel-close! logs))

  ;; Consumer: process with transducer
  (go (for-channel (msg logs)
        (let ((xrf (log-xform (lambda (acc x) (println "ERROR: ~a" x) acc))))
          (xrf #f msg)))))

Exports

mappingprocedure

Create a mapping transducer.

Transforms each element by applying f.

(transduce (mapping square) conj '() '(1 2 3))  ; => (1 4 9)
filteringprocedure

Create a filtering transducer.

Keeps only elements satisfying the predicate.

(transduce (filtering even?) conj '() '(1 2 3 4))  ; => (2 4)
takingprocedure

Create a taking transducer.

Takes at most n elements, then terminates early.

(transduce (taking 3) conj '() '(1 2 3 4 5))  ; => (1 2 3)
droppingprocedure

Create a dropping transducer.

Skips the first n elements.

(transduce (dropping 2) conj '() '(1 2 3 4 5))  ; => (3 4 5)
taking-whileprocedure

Create a taking-while transducer.

Takes elements while predicate is true, then stops.

(transduce (taking-while (lambda (x) (< x 4))) conj '() '(1 2 3 4 5))
; => (1 2 3)

Create a dropping-while transducer.

Drops elements while predicate is true, then takes the rest.

(transduce (dropping-while (lambda (x) (< x 3))) conj '() '(1 2 3 4 5))
; => (3 4 5)
catprocedure

Concatenating transducer.

Flattens one level of nesting.

(transduce cat conj '() '((1 2) (3 4)))  ; => (1 2 3 4)
mapcatprocedure

Mapcat transducer (map then concatenate).

Like (comp (mapping f) cat) but slightly more efficient.

(transduce (mapcat (lambda (x) (list x x))) conj '() '(1 2 3))
; => (1 1 2 2 3 3)
compprocedure

Compose transducers left-to-right.

Unlike function composition, transducers compose in reading order.

(comp (filtering even?) (mapping square) (taking 3))
conjprocedure

Reducer for building lists.

(transduce (mapping square) conj '() '(1 2 3))  ; => (1 4 9)
conj-vecprocedure

Reducer for building vectors.

Note: builds a list then converts (vectors are immutable).

conj-dictprocedure

Reducer for building dicts from (key . value) pairs.

transduceprocedure

Apply a transducer to a collection.

The core transducer execution function.

(transduce (mapping square) conj '() '(1 2 3))  ; => (9 4 1)
(transduce (mapping square) + 0 '(1 2 3))       ; => 14
intoprocedure

Transform and collect into a collection of the same type.

(into '() (mapping square) '(1 2 3))   ; => (9 4 1)
(into #() (mapping square) '(1 2 3))   ; => #(1 4 9)
sequenceprocedure

Transform a collection, preserving its type.

(sequence (mapping square) '(1 2 3))   ; => (1 4 9)
(sequence (mapping square) #(1 2 3))   ; => #(1 4 9)
mapprocedure

Apply a procedure to each element, returning a collection of the same type.

Works on lists, vectors, arrays, and dicts.

(map square '(1 2 3))   ; => (1 4 9)
(map square #(1 2 3))   ; => #(1 4 9)
(map cdr #{ a: 1 b: 2 }) ; => (1 2) - maps over entries
filterprocedure

Return elements satisfying a predicate, preserving collection type.

(filter even? '(1 2 3 4))   ; => (2 4)
(filter even? #(1 2 3 4))   ; => #(2 4)
foldprocedure

Reduce a collection with a procedure.

Works on lists, vectors, arrays, and dicts.

(fold + 0 '(1 2 3 4))   ; => 10
(fold + 0 #(1 2 3 4))   ; => 10
for-eachprocedure

Apply a procedure to each element for side effects.

(for-each println '(1 2 3))
(for-each println #(1 2 3))
anyprocedure

Test if any element satisfies a predicate.

(any even? '(1 3 4 5))  ; => #t
(any even? #(1 3 5 7))  ; => #f
everyprocedure

Test if all elements satisfy a predicate.

(every even? '(2 4 6))  ; => #t
(every even? #(2 3 4))  ; => #f
findprocedure

Find the first element satisfying a predicate.

Returns #f if no element matches.

(find even? '(1 3 4 5))  ; => 4
(find even? '(1 3 5 7))  ; => #f