; Can you abstract accumulators into a single function?
; ------------------------------
; The Little Lisper 3rd Edition
; Chapter 9
; Exercise 7
; Common Lisp
; http://t...content-available-to-author-only...r.com/thelittlelisper
; http://t...content-available-to-author-only...t.com/2010/06/little-lisper-chapter-9-lamdba-ultimate.html
; http://t...content-available-to-author-only...t.com/2010/06/little-lisper.html
; ------------------------------

(defun operator (aexp_)
  (car (cdr aexp_)))

(print (operator '(1 + 2)))
; +

(defun isoperator (a)
  (cond
   ((null a) NIL)
   ((eq a '+) t)
   ((eq a '*) t)
   ((eq a '^) t)
   (t NIL)))

(print (isoperator '^))
; T

(print (isoperator (operator '(1 + 2))))
; T

(defun 1st-sub-expr (aexp_)
  (car aexp_))

(print (1st-sub-expr '(1 + 2)))
; 1

(defun 2nd-sub-expr (aexp_)
  (car (cdr (cdr aexp_))))

(print (2nd-sub-expr '(1 + 2)))
; 2

(defun sub1 (n)
  (- n 1))

(defun notatom (lat)
  (not (atom lat)))

(defun number__ (n)
  (cond
   ((null n) nil)
   ((notatom n) nil)
  ((= 0 n) t)
   (t (number__ (sub1 n)))))

(print (number__ 10))
;T
      
(defun count-op (aexp_)
  (cond
   ((null aexp_) 0)
   ((number__ aexp_) 0)
   ((isoperator (operator aexp_))
    (+ 
    (+ 1 (count-op (1st-sub-expr aexp_)))
    (count-op (2nd-sub-expr aexp_)))
    )
   (t 0)))

(print (count-op '(3 * (4 * (5 * 6)))))


(defun count-op-f (aexp_ op-function)
  (cond
   ((null aexp_) 0)
   ((number__ aexp_) 0)
   ((eq (operator aexp_) op-function)
    (+ 
     (+ 1
       (count-op-f (1st-sub-expr aexp_) op-function))
    (count-op-f (2nd-sub-expr aexp_) op-function))
    )
   (t 0)))

(print (count-op-f '(1 + 1)  '+))
; 1

(print (count-op-f '(1 + (1 + 1)) '+))
; 2

(print (count-op-f '(3 * (4 * (5 * 6)))  '*))
; 3

(print (count-op-f '(1 - 1)  '+))
; 0
