(define reverse
  (lambda (ls)
    (if (null? ls)
        '()
        (append (reverse (cdr ls))
                (list (car ls))))))

(define reverse-all
  (lambda (ls)
    (cond ((null? ls) '())
          ((pair? (car ls))
           (append (reverse-all (cdr ls))
                   (list (reverse-all (car ls)))))
           (else
           (append (reverse-all (cdr ls))
                   (list (car ls)))))))

(define wrap
  (lambda (x)
    (if (pair? x)
        x
        (list x))))

(define flatten
  (lambda (ls)
    (if (null? ls)
        '()
        (append (wrap (car ls))
                (flatten (cdr ls))))))

;; better
(define flatten
  (lambda (ls)
    (apply append (map wrap ls))))

(define flatten-all
  (lambda (ls)
    (cond ((null? ls) '())
          ((pair? (car ls))
           (append (flatten-all (car ls))
                   (flatten-all (cdr ls))))
          (else
           (cons (car ls)
                 (flatten-all (cdr ls)))))))

;; better
(define reverse-all
  (lambda (ls)
    (if (pair? ls)
        (reverse (map reverse-all ls))
        ls)))

(define flatten-all
   (lambda (ls)
    (if (pair? ls)
        (flatten (map flatten-all ls))
        ls)))

;; the pattern is abstracted as a higher-order function
(define make-deep
  (lambda (proc)
    (letrec
       ((pattern
         (lambda (ls)
           (if (pair? ls)
               (proc (map pattern ls))
               ls)))
        pattern))))

;; best
(define make-deep
  (lambda (proc)
    (lambda (ls)
      (if (pair? ls)
          (proc (map (make-deep proc) ls))
          ls))))

(define reverse-all
  (make-deep reverse))

(define flatten-all
  (make-deep flatten))

;; the higher order function is used in new ways
(define scramble
  (lambda (ls)
    (list (cadr ls)
          (car ls)
          (caddr ls))))

(define infix->prefix
  (make-deep scramble))

(define calculator
  (make-deep
   (lambda (ls)
     (let ((op (car ls)))
       (apply
        (cond ((eq? op '+) +)
              ((eq? op '-) -)
              ((eq? op '*) *)
              (else /))
        (cdr ls))))))