出于教育目的,我尝试使用CLOS实现一个简单的代数OOP示例。就我所能说的来说,它的功能是应该的。该方法的目的是实现一个简单的表意OOP多态性示例。为了获得更好的学习体验,我想展示一下代码,以获得建议、批评等等。
;; 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发布于 2012-08-24 19:14:06
(defmethod evaluate ((node op-node))
(apply (value node)
(list (evaluate (left-node node))
(evaluate (right-node node)))))可以写:
(defmethod evaluate ((node op-node))
(funcall (value node)
(evaluate (left-node node))
(evaluate (right-node node))))对于这个示例,您可以使用一个binop类并使用相应的函数实例化它,因为它们共享相同的evaluate方法,而不是针对每个二进制操作使用不同的子类,但这取决于您还想对节点做什么。(例如,您可能希望对每个方法都有不同的print-object方法。)
(同样,在未确定的符号上使用toplevel setfs也被认为是不好的风格,但我认为这只是为了测试和演示目的。在实际代码中,应该使用defparameter或defvar。)
发布于 2012-08-24 20:30:08
(defmethod evaluate (value-node)
(value value-node))尝试调用(评估)。为什么要调用该方法?
https://codereview.stackexchange.com/questions/15039
复制相似问题