GaucheでHaskellのscanl

Haskellのscanlに相当するものがなかったので書いた.
(修正 9:24)

(use gauche.collection)

(define (scan-with-iterator+builder f seed end? next add! get)
  (let loop ((seed seed))
    (add! seed)
    (if (end?)
        (get)
        (loop (f (next) seed)))))

(define-method scan-to ((class <class>) f seed (coll <collection>))
  (with-iterator (coll end? next)
    (with-builder (class add! get)
      (scan-with-iterator+builder f seed end? next add! get))))

(define-method scan (f seed (coll <collection>))
  (scan-to <list> f seed coll))

(define-method scan1-to ((class <class>) f (coll <collection>))
  (with-iterator (coll end? next)
    (with-builder (class add! get)
      (if (end?)
          (get)
          (scan-with-iterator+builder f (next) end? next add! get)))))

(define-method scan1 (f (coll <collection>))
  (scan1-to <list> f coll))

コールバックの引数の順序はfoldやmap-accumに倣った.

(追加 10:07)scan-right

(use gauche.sequence)

(define-method scan-right (f seed (coll <sequence>))
  (with-iterator (coll end? next)
    (call-with-values
        (rec (loop)
          (if (end?)
              (values seed '())
              (let1 v (next)
                (receive (seed r) (loop)
                  (values (f v seed) (cons seed r))))))
      cons)))

(define-method scan-right-to ((class <class>) f seed (coll <sequence>))
  (coerce-to class (scan-right f seed coll)))

(define-method scan-right1 (f (coll <sequence>))
  (with-iterator (coll end? next)
    (if (end?)
        '()
        (call-with-values
            (rec (loop)
              (let1 v (next)
                (if (end?)
                    (values v '())
                    (receive (seed r) (loop)
                      (values (f v seed) (cons seed r))))))
          cons))))

(define-method scan-right1-to ((class <class>) f seed (coll <sequence>))
  (coerce-to class (scan-right1 f seed coll)))

汚い…なんとかならんのか.