chickadee » srfi-116 » iunfold-right

iunfold-right p f g seed #!optional tailprocedure

iunfold-right constructs an ilist with the following loop:

(let lp ((seed seed) (lis tail))
  (if (p seed) lis
      (lp (g seed)
          (ipair (f seed) lis))))
p
Determines when to stop unfolding.
f
Maps each seed value to the corresponding ilist element.
g
Maps each seed value to next seed value.
seed
The "state" value for the unfold.
tail
ilist terminator; defaults to '().

In other words, we use g to generate a sequence of seed values seed, (g seed), (g2 seed), (g3 seed), ... These seed values are mapped to ilist elements by f, producing the elements of the result ilist in a right-to-left order. P says when to stop.

iunfold-right is the fundamental iterative ilist constructor, just as ifold is the fundamental iterative ilist consumer. While iunfold-right may seem a bit abstract to novice functional programmers, it can be used in a number of ways:

;; Ilist of squares: 1^2 ... 10^2
(iunfold-right zero?
              (lambda (x) (* x x))
              (lambda (x) (- x 1))
              10)

;; Reverse a proper ilist.
(iunfold-right null-ilist? icar icdr lis)

;; Read current input port into an ilist of values.
(iunfold-right eof-object? values (lambda (x) (read)) (read))

;; (iappend-reverse rev-head tail)
(iunfold-right null-ilist? icar icdr rev-head tail)