For educational purposes I've tried to implement a simple algebraic OOP example using CLOS. The functionality is as far as I can say as it is supposed to be. The intended approach was to implement a simple example of ideomatic OOP polymorphism. For a greater learning experience I've wanted to show the code to get suggestions, critic and so on.
;; main node class, most general
(defclass node ()
;; abstract class for nodes
((value :initarg :value :reader value)))
(defgeneric evaluate (node)
(:documentation "the standard evaluation"))
;; node containing an operation, more specific
(defclass op-node (node)
;; abstract class for a node containing an operation
((left-node :initform nil :initarg :left-node :reader left-node)
(right-node :initform nil :initarg :right-node :reader right-node)))
(defmethod evaluate ((node op-node))
(apply (value node)
(list (evaluate (left-node node))
(evaluate (right-node node)))))
;; concrete nodes
(defclass add-node (op-node)
;; class for addition
((value :initform #'+ :reader value)))
(defclass minus-node (op-node)
;; class for subtraction
((value :initform #'- :reader value)))
(defclass multi-node (op-node)
;; class for multiplication
((value :initform #'* :reader value)))
(defclass value-node (node)
;; class for a node containing a numerical value
((value :initarg :value :reader value)))
(defmethod evaluate (value-node)
(value value-node))
;; 1 + 3
(setf *simple-add* (make-instance 'add-node
:left-node (make-instance 'value-node :value 1)
:right-node (make-instance 'value-node :value 3)))
;; 1 * 10
(setf *simple-multi* (make-instance 'multi-node
:left-node (make-instance 'value-node :value 1)
:right-node (make-instance 'value-node :value 10)))
;; (1 + 3) + (1 * 10)
(setf *advanced-add* (make-instance 'add-node
:left-node *simple-add*
:right-node *simple-multi*))
(evaluate *simple-add*) ;; => 4
(evaluate *simple-multi* ;; => 10
(evaluate *advanced-add*) ;; => 14