Hello Guilers, Since I find this exercise interesting, I come up with another demo. The trick is to think of string as a list of characters (like in Haskell) and to use the fact that append can be written as an unfold.
Let's begin: 1. Use SRFI-1 and SRFI-26 (use-modules (srfi srfi-1) (srfi srfi-26)) 2. Implement append using unfold (define (append a b) (unfold null? car cdr a (const b))) Test it: (append '(1 2 3) '(4 5 6)) => (1 2 3 4 5 6) 3. Extend append to allow any number of arguments (define append (lambda args (define (%append a b) (unfold null? car cdr a (const b))) (fold-right %append '() args))) Test it: (append '(1 2 3) '(4 5 6) '(7 8 9)) => (1 2 3 4 5 6 7 8 9) 4. "Port" the procedure to "string"-land First, notice 'unfold' takes a TAIL-GEN procedure to generate the tail, while string-unfold takes a BASE string, not a procedure. So, let's replace '(const b)' with 'b'. Next, replace 'null?' with 'string-null?', 'car' with '(cut string-ref <> 0)' and 'cdr' with '(cut string-drop <> 1)' (define (string-append a b) (string-unfold string-null? (cut string-ref <> 0) (cut string-drop <> 1) a b)) Test it: (string-append "123" "456") => "456123" Oops, we got the a and b reversed. 5. Reverse a and b (define (string-append a b) (string-unfold string-null? (cut string-ref <> 0) (cut string-drop <> 1) b a)) Test it: (string-append "123" "456") => "123456" Now it works. 6. Extend again to allow any number of arguments (define string-append (lambda args (define (%string-append a b) (string-unfold string-null? (cut string-ref <> 0) (cut string-drop <> 1) b a)) (fold-right %string-append "" args))) Test it: (string-append "123" "456" "789") => "123456789" DONE! Cheers, Alex Matt Wette <matt.we...@gmail.com> writes: > Just for kicks, to learn string-unfold, I made an ugly version of > string-append: > > (define (ugly-string-append . str-l) > > ;; p: seed |-> #t|#f predicate to indicate stop > (define (p seed) (null? seed)) > > ;; f: seed |-> char output function > (define (f seed) (string-ref (cddar seed) (caar seed))) > > ;; g: seed |-> seed transition function > (define (g seed) (let* ((head (car seed)) (tail (cdr seed)) > (ix (car head)) (ln (cadr head)) (st (cddr head))) > (if (eq? (1+ ix) ln) tail > (cons (cons* (1+ ix) ln st) tail)))) > > ;; s: seed = ((ix1 ln1 . st1) (ix2 ln2 . st2) ...) > ;; where ix is curr index, ln is string-length, and st is string > (define s (map (lambda (s) (cons* 0 (string-length s) s)) str-l)) > > (string-unfold p f g s)) > > (ugly-string-append "abc" "def") => "abcdef"
signature.asc
Description: PGP signature