123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172 |
- (library (list-helpers)
- (export list-right-pad
- flatten)
- (import
- (except (rnrs base) let-values map)
- (only (guile)
- lambda* λ)
- (ice-9 match))
- (define list-right-pad
- (λ (lst pad-count pad-value)
- (cond
- [(= pad-count 0) lst]
- [(null? lst)
- (cons pad-value
- (list-right-pad lst
- (- pad-count 1)
- pad-value))]
- [else
- (cons (car lst)
- (list-right-pad (cdr lst)
- (- pad-count 1)
- pad-value))])))
- ;; This one is a read brain twister.
- (define (flatten lst)
- (let loop ([remaining-lst lst]
- [acc '()])
- (cond
- [(null? remaining-lst) acc]
- ;; If we have a list recur with the head of the list and the
- ;; cdr. Since the acc argument will be consed to the end
- ;; ultimately (see else branch), we can call loop for the head
- ;; of the list and use the result of flattening the tail of the
- ;; list as new acc.
- ;; Since the evaluation order is to evaluate arguments for
- ;; function calls first, we put off the flattening of the head
- ;; of the list until later. The tail of the list will be
- ;; flattened first.
- [(pair? remaining-lst)
- ;; If head is an atom the call will go the the else branch,
- ;; where it will be the `remaining-lst`. It will wait there to
- ;; be consed onto the result for the other call to loop. This
- ;; basically builds up a chain of cons, each waiting for the
- ;; second argument to be computed.
- ;; If head is a list, it will be flattened, which results in
- ;; having the cons chain for that list, which waits for the
- ;; flattened tail to be consed onto that.
- ;; The acc argument is used to thread in the results of
- ;; flattening parts of the list, which will only be seen
- ;; later. It provides a handle onto the later flattened parts
- ;; of the list, to be consed onto those in the else branch. It
- ;; is quite clever actually.
- (loop (car remaining-lst)
- (loop (cdr remaining-lst)
- acc))]
- ;; If we have an atom, use the atom as is and cons it onto the
- ;; accumulated. The value for acc is computed in the (pair?
- ;; remaining-lst) branch, by another call to loop.
- [else
- (cons remaining-lst acc)]))))
|