Transducers - sentinel in collector vs transduce added by DeeEff on Sat Jan 14 21:06:28 2023

(import transducers)

;; In v0.1.0 we can use multiple-arity functions like `+`
;;
;; Any function that takes 0-N arguments (N-arity) can be used, and they don't
;; need to be redefined in any special way.
(transduce list-fold
           values
           +
           100
           (list 1 2 3 4 5))
; => 115

;; vs.

;; In v0.2.0 we have to make a separate collector that can accept the sentinel.
;;
;; Unfortunately this means that we can't necessarily take any function here -
;; there's no way to seed these functions.

;; This works, but you cannot seed the procedure.
;;
;; As a result, you have to now go outside the transducer to achieve the same
;; results. This isn't a big deal for `+`, but isn't necessarily possible with
;; other functions that don't have a zero-arity variant.
;;
;; Procedures defined as (define (foo . args) ...) will work.
;;
;; Procedures defined as (deifne (foo arg . args) ...) will not.
(tranduce list-fold
          values
          +
          (list 1 2 3 4 5))

; => 15

;; Conversely, using collect-sum here will allow you to achieve everything
;; through the transduce call. However, this involves defining another
;; procedure with case-lambda.
(define (collect-sum #!optional (sentinel 0))
  (case-lambda
    (() sentinel)
    ((result) result)
    ((result item) (+ result item))))

(transduce list-fold
           values
           (collect-sum 100)
           (list 1 2 3 4 5))
; => 115