Next: lists fold map, Previous: lists fold reduce, Up: lists fold [Index]
Generate a list from a starting value; return the result. It is is the
fundamental recursive list constructor, just as fold-right
is the
fundamental recursive list consumer. It is best described by its basic
recursion:
(unfold stop? map-to-elm seed-step seed tail-gen) = (if (stop? seed) (tail-gen seed) (cons (map-to-elm seed) (unfold stop? map-to-elm seed-step (seed-step seed) tail-gen)))
The arguments are:
Determines when to stop: it is applied to the current seed value, and if
the return value is #t
: unfolding stops. If it evaluates to
#t
at the first invocation: the return value of unfold
is
the return value of tail-gen.
Maps each seed value to the corresponding list element. It is applied to the current seed value and must return the value to append to the result list.
Maps each seed value to next seed value.
The “state” value for the unfold. It is the first seed value.
Applied to the seed value that caused stop?
to return #t
,
must return the tail of the result list. Defaults to (lambda (x)
'())
.
While unfold
may seem a bit abstract to novice functional
programmers, it can be used in a number of ways:
;; List of squares: 1^2 ... 5^2 (unfold (lambda (x) (> x 5)) (lambda (x) (* x x)) (lambda (x) (+ x 1)) 1) ⇒ (1 4 9 16 25) ;; Copy a proper list. (unfold null-list? car cdr '(1 2 3 4 5)) ⇒ (1 2 3 4 5) ;; Read current input port into a list of values. (unfold eof-object? values (lambda (x) (read)) (read)) ;; Copy a possibly non-proper list: (unfold not-pair? car cdr '(1 2 3 4 . 5) values) ⇒ (1 2 3 4 . 5) ;; Append HEAD onto TAIL: (unfold null-list? car cdr '(1 2 3) (lambda (x) '(4 5 6))) ⇒ (1 2 3 4 5 6)
NOTE Interested functional programmers may enjoy noting that
fold-right
andunfold
are in some sense inverses. That is, given operations knull?, kar, kdr, kons, and knil satisfying:(kons (kar x) (kdr x)) = x and (knull? knil) = #tthen:
(fold-right kons knil (unfold knull? kar kdr x)) = xand:
(unfold knull? kar kdr (fold-right kons knil x)) = xThis combinator sometimes is called an “anamorphism”; when an explicit tail-gen procedure is supplied, it is called an “apomorphism”.
Generate a list from a starting value; return the result. It is the
fundamental iterative list constructor, just as fold
is the
fundamental iterative list consumer. Construct a list with the
following loop:
(let loop ((seed seed) (ell tail)) (if (stop? seed) ell (loop (seed-step seed) (cons (map-to-elm seed) ell))))
Arguments are:
Determine when to stop unfolding.
Map each seed value to the corresponding list element.
Map each seed value to next seed value.
The “state” value for the unfold.
List terminator; defaults to '()
.
While unfold-right
may seem a bit abstract to novice functional
programmers, it can be used in a number of ways:
;; List of squares: 1^2 ... 10^2 (unfold-right zero? (lambda (x) (* x x)) (lambda (x) (- x 1)) 5) ⇒ (1 4 9 16 25) ;; Reverse a proper list. (unfold-right null-list? car cdr '(1 2 3 4 5)) ⇒ (5 4 3 2 1) ;; Read current input port into a list of values. (unfold-right eof-object? values (lambda (x) (read)) (read)) ;; Equivalent to: (append-reverse rev-head tail) (unfold-right null-list? car cdr '(3 2 1) '(4 5 6)) ⇒ (1 2 3 4 5 6)
NOTE Interested functional programmers may enjoy noting that
fold
andunfold-right
are in some sense inverses. That is, given operations knull?, kar, kdr, kons, and knil satisfying:(kons (kar x) (kdr x)) = x and (knull? knil) = #tthen:
(fold kons knil (unfold-right knull? kar kdr x)) = xand:
(unfold-right knull? kar kdr (fold kons knil x)) = x.This combinator presumably has some pretentious mathematical name; interested readers are invited to communicate it to the author.
Next: lists fold map, Previous: lists fold reduce, Up: lists fold [Index]