Evaluator for adding and subtracting algebraic expressions I wrote a little program that adds and subtracts some algebraic expressions.

In my code (2 x 3) represents \$2x^3\$.

The purpose of this post is to get some feedback; moreover, I would like to know how to make it perform better and improve it.

I ran this program on a Mac with SBCL + Emacs.

(defun compute (exp)
  (cond ((term? exp) exp)
    ((expression? exp)
     (make (compute (first-expression exp))
           (compute (second-expression exp))
           (operator exp)))
    (t (error "Unknown Expression Type --COMPUTE" exp))))

(defun term? (exp)
  (or (numberp exp)
      (monomial? exp)))

(defun monomial? (exp)
  (and (consp exp)
       (numberp (car exp))
       (symbolp (car (cdr exp)))
       (numberp (car (cdr (cdr exp))))))


(defun expression? (exp)
  (or (eql (car exp) '+)
      (eql (car exp) '*)
      (eql (car exp) '-)))

(defun first-expression (exp) (car (cdr exp)))

(defun second-expression (exp) (car (cdr (cdr exp))))

(defun operator (exp) (car exp))

(defun make (e1 e2 op)
  (cond ((eql op '+)
     (make-addition e1 e2))
        ((eql op '-)
     (make-subtraction e1 e2))
    (t (make-product e1 e2))))


I wrote the following higher order procedures because version 1 had
a lot patterns.

(defun make-addition (e1 e2)
  (make-exp e1
        e2
        '+
        #'add-monomials))

(defun make-subtraction (e1 e2)
  (make-exp e1
        e2
        '-
        #'subtract-monomials))


(defun make-exp (e1 e2 op term)
  (cond ((eql e1 0) e2)
    ((eql e2 0) e1)
    ((&amp;number? e1 e2) (+ e1 e2))
    ((&amp;monomial? e1 e2)
     (funcall term e1 e2))
    (t (list op e1 e2))))

;; make-product
(defun make-product (e1 e2) (list '* e1 e2))

(defun &amp;number? (e1 e2)
  (and (numberp e1)
       (numberp e1)))

(defun &amp;monomial? (e1 e2)
  (and (monomial? e1)
       (monomial? e2)))


(defun add-monomials (e1 e2)
  (compute-monomials e1
             e2
             #'+
             '+))

(defun subtract-monomials (e1 e2)
  (compute-monomials e1
             e2
             #'-
             '-))

(defun compute-monomials (e1 e2 term op)
  (if (same-variable? e1 e2)
      (make-monomial (funcall term (coeff e1) (coeff e2))
             (variablex e1)
             (exponent e1))
      (list op e1 e2p)))

(defun variablex (exp) (car (cdr exp)))

(defun same-variable? (e1 e2)
  (eql (variablex e1) (variablex e2)))

(defun make-monomial (coeff var exp)
  (list coeff var exp))

(defun coeff (exp) (car exp))

(defun exponent (exp) (car (cdr (cdr exp))))
Make sure your code is indented correctly here. It isn't.

Then document your code at least with some minimum amount of explanations and structure.

Common Lisp has ways to comment code:

;;;; program comment

;;; section comment

(defun bar ()

  "This is a retrievable function documentation
string, which
can be spread over many lines."

  (let ((foo (random 100)))
   ;;  indented code comment
   (+ foo 3)   ; inline code comment
   ))

#|
     Block comments
|#


Then one can retrieve the function documentation with some IDE keystrokes/mechanisms and:

(documentation 'bar 'function)


Some hints:

(defun expression? (exp)
  (or (eql (car exp) '+)
      (eql (car exp) '*)
      (eql (car exp) '-)))

(case exp
  ((+ * -) t)
  (otherwise nil))

(member (car exp) '(+ * -))

(defun first-expression (exp) (car (cdr exp)))

(cadr exp)
(second exp)

(defun second-expression (exp) (car (cdr (cdr exp))))

(caddr exp)
(third exp)


(defun make (e1 e2 op)
  (cond ((eql op '+)
         (make-addition e1 e2))
        ((eql op '-)
         (make-subtraction e1 e2))
        (t (make-product e1 e2))))

(case op
  (+ ...)
  (- ...)
  (otherwise ...))