feat: add collecting transducer to accumulate partial sums

This commit is contained in:
Edward
2021-01-04 02:01:19 -08:00
parent e08fccfe1b
commit d0e894f739
3 changed files with 34 additions and 17 deletions

View File

@ -22,11 +22,7 @@
(defpackage :data-lens.transducers.internals (defpackage :data-lens.transducers.internals
(:use :cl) (:use :cl)
(:export (:export #:unwrap #:init #:reduce-generic #:stepper))
#:unwrap
#:init
#:reduce-generic
#:stepper))
(defpackage :data-lens.transducers (defpackage :data-lens.transducers
(:use :cl) (:use :cl)
@ -35,13 +31,7 @@
(:export #:mapping :filtering :deduping :catting :splitting (:export #:mapping :filtering :deduping :catting :splitting
#:exit-early :taking :dropping :transduce #:exit-early :taking :dropping :transduce
#:hash-table-builder :vector-builder :list-builder #:hash-table-builder :vector-builder :list-builder
#:mv-mapping #:collecting #:mv-mapping #:mv-selecting
#:mv-selecting #:hash-table-select #:mv-filtering #:mapcatting
#:hash-table-select #:lazy-sequence #:compressing-runs #:iota
#:mv-filtering #:repeating #:repeating*))
#:lazy-sequence
#:compressing-runs
#:mapcatting
#:iota
#:repeating
#:repeating*))

View File

@ -107,6 +107,16 @@
(2 4 4 4) (2 5 5 5) (2 4 4 4) (2 5 5 5)
(3 6 6 6)))))) (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:def-test catting (:suite :data-lens.transducers)
(5am:is (equal '(1 1 2 1 2 2 3 3 4 1) (5am:is (equal '(1 1 2 1 2 2 3 3 4 1)
(data-lens.transducers:transduce (data-lens.transducers:catting) (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) (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:transduce (data-lens.transducers:mapcatting 'list)
'data-lens.transducers:list-builder '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:def-test splitting (:suite :data-lens.transducers)
(5am:is (equal '((2 0) (3 1) (4 2)) (5am:is (equal '((2 0) (3 1) (4 2))
@ -125,7 +141,6 @@
'data-lens.transducers:list-builder 'data-lens.transducers:list-builder
'(1 2 3))))) '(1 2 3)))))
(5am:def-test transducer-composition (:suite :data-lens.transducers) (5am:def-test transducer-composition (:suite :data-lens.transducers)
(5am:is (equal '(3 5 7) (5am:is (equal '(3 5 7)
(data-lens.transducers:transduce (data-lens: (data-lens.transducers:transduce (data-lens:

View File

@ -86,6 +86,18 @@
(funcall rf it last) (funcall rf it last)
it))))))) 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)) (defun deduping (&optional (test 'eql))
(compressing-runs :test test)) (compressing-runs :test test))