; dollar format

(define (take n xs)
  (let loop ((n n) (xs xs) (ys '()))
    (if (or (zero? n) (null? xs))
        (reverse ys)
        (loop (- n 1) (cdr xs)
              (cons (car xs) ys)))))

(define (drop n xs)
  (let loop ((n n) (xs xs))
    (if (or (zero? n) (null? xs)) xs
      (loop (- n 1) (cdr xs)))))

(define (digits n . args)
  (let ((b (if (null? args) 10 (car args))))
    (let loop ((n n) (d '()))
      (if (zero? n) d
          (loop (quotient n b)
                (cons (modulo n b) d))))))

(define (dollar x)
  (define (commas n)
    (let ((xs (reverse (map number->string (digits n)))))
      (let loop ((xs (drop 3 xs)) (zs (reverse (take 3 xs))))
        (if (null? xs) (apply string-append zs)
          (loop (drop 3 xs) (append (reverse (take 3 xs)) (list ",") zs))))))
  (define (zero n)
    (if (zero? n) "00"
      (if (< n 10) (string-append "0" (number->string n))
        (number->string n))))
  (let* ((dollars (inexact->exact (floor x)))
         (cents (inexact->exact (round (* 100 (- x dollars))))))
    (string-append "$" (commas dollars) "." (zero cents))))

(display (dollar 1234567.8912)) (newline)