- (string-unfold p f g seed [base make-final]) -> stringprocedure
This is a fundamental constructor for strings.
- G is used to generate a series of "seed" values from the initial seed: SEED, (G SEED), (G^2 SEED), (G^3 SEED), ...
- P tells us when to stop -- when it returns true when applied to one of these seed values.
- F maps each seed value to the corresponding character in the result string. These chars are assembled into the string in a left-to-right order.
- BASE is the optional initial/leftmost portion of the constructed string; it defaults to the empty string "".
- MAKE-FINAL is applied to the terminal seed value (on which P returns true) to produce the final/rightmost portion of the constructed string. It defaults to (lambda (x) "").
More precisely, the following (simple, inefficient) definitions hold:
;;; Iterative (define (string-unfold p f g seed base make-final) (let lp ((seed seed) (ans base)) (if (p seed) (string-append ans (make-final seed)) (lp (g seed) (string-append ans (string (f seed))))))) ;;; Recursive (define (string-unfold p f g seed base make-final) (string-append base (let recur ((seed seed)) (if (p seed) (make-final seed) (string-append (string (f seed)) (recur (g seed)))))))
string-unfold is a fairly powerful string constructor -- you can use it to convert a list to a string, read a port into a string, reverse a string, copy a string, and so forth. Examples:
(port->string p) = (string-unfold eof-object? values (lambda (x) (read-char p)) (read-char p)) (list->string lis) = (string-unfold null? car cdr lis) (string-tabulate f size) = (string-unfold (lambda (i) (= i size)) f add1 0)
To map F over a list LIS, producing a string:
(string-unfold null? (compose f car) cdr lis)
Interested functional programmers may enjoy noting that string-fold-right and string-unfold 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) = #t
then
(string-fold-right KONS KNIL (string-unfold KNULL? KAR KDR X)) = X
and
(string-unfold KNULL? KAR KDR (string-fold-right KONS KNIL S)) = S.
The final string constructed does not share storage with either BASE or the value produced by MAKE-FINAL.
This combinator sometimes is called an "anamorphism."
Note: implementations should take care that runtime stack limits do not cause overflow when constructing large (e.g., megabyte) strings with string-unfold.