diff --git a/package.lisp b/package.lisp index 8d3e3bc..78045fa 100644 --- a/package.lisp +++ b/package.lisp @@ -22,11 +22,7 @@ (defpackage :data-lens.transducers.internals (:use :cl) - (:export - #:unwrap - #:init - #:reduce-generic - #:stepper)) + (:export #:unwrap #:init #:reduce-generic #:stepper)) (defpackage :data-lens.transducers (:use :cl) @@ -35,13 +31,7 @@ (:export #:mapping :filtering :deduping :catting :splitting #:exit-early :taking :dropping :transduce #:hash-table-builder :vector-builder :list-builder - #:mv-mapping - #:mv-selecting - #:hash-table-select - #:mv-filtering - #:lazy-sequence - #:compressing-runs - #:mapcatting - #:iota - #:repeating - #:repeating*)) + #:collecting #:mv-mapping #:mv-selecting + #:hash-table-select #:mv-filtering #:mapcatting + #:lazy-sequence #:compressing-runs #:iota + #:repeating #:repeating*)) diff --git a/t/transducer.lisp b/t/transducer.lisp index 1112076..952f4de 100644 --- a/t/transducer.lisp +++ b/t/transducer.lisp @@ -107,6 +107,16 @@ (2 4 4 4) (2 5 5 5) (3 6 6 6)))))) +(5am:def-test collecting (:suite :data-lens.transducers) + (5am:is (equal '(1 3 6 9 13 18 22 27 33 40) + (data-lens.transducers:transduce (data-lens:• (data-lens.transducers:taking 5) + (data-lens.transducers:mapcatting 'identity) + (data-lens.transducers::collecting '+)) + 'data-lens.transducers:list-builder + (loop for x from 1 + repeat 4 + collect (data-lens.transducers:iota :start x :count x)))))) + (5am:def-test catting (:suite :data-lens.transducers) (5am:is (equal '(1 1 2 1 2 2 3 3 4 1) (data-lens.transducers:transduce (data-lens.transducers:catting) @@ -117,7 +127,13 @@ (5am:is (equal '(1 1 2 1 2 2 3 3 4 1) (data-lens.transducers:transduce (data-lens.transducers:mapcatting 'list) 'data-lens.transducers:list-builder - '(1 1 2 1 2 2 3 3 4 1))))) + '(1 1 2 1 2 2 3 3 4 1)))) + (5am:is (equal '(0 0 1 0 1 2) + (data-lens.transducers:transduce (data-lens.transducers:mapcatting 'identity) + 'data-lens.transducers:list-builder + (list (data-lens.transducers:iota :count 1) + (data-lens.transducers:iota :count 2) + (data-lens.transducers:iota :count 3)))))) (5am:def-test splitting (:suite :data-lens.transducers) (5am:is (equal '((2 0) (3 1) (4 2)) @@ -125,7 +141,6 @@ 'data-lens.transducers:list-builder '(1 2 3))))) - (5am:def-test transducer-composition (:suite :data-lens.transducers) (5am:is (equal '(3 5 7) (data-lens.transducers:transduce (data-lens:• diff --git a/transducers.lisp b/transducers.lisp index 18b8bb3..eee9581 100644 --- a/transducers.lisp +++ b/transducers.lisp @@ -86,6 +86,18 @@ (funcall rf it last) it))))))) + +(defun collecting (collector) + (lambda (rf) + (let (sofar) + (transducer-lambda + ((acc next) + (if sofar + (setf sofar (funcall collector sofar next)) + (setf sofar next)) + (funcall rf acc sofar)))))) + + (defun deduping (&optional (test 'eql)) (compressing-runs :test test))