首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于CLOS的简单"if"-less代数计算

基于CLOS的简单"if"-less代数计算
EN

Code Review用户
提问于 2012-08-24 15:55:40
回答 2查看 97关注 0票数 3

出于教育目的,我尝试使用CLOS实现一个简单的代数OOP示例。就我所能说的来说,它的功能是应该的。该方法的目的是实现一个简单的表意OOP多态性示例。为了获得更好的学习体验,我想展示一下代码,以获得建议、批评等等。

代码语言:javascript
复制
;; 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
EN

回答 2

Code Review用户

回答已采纳

发布于 2012-08-24 19:14:06

代码语言:javascript
复制
(defmethod evaluate ((node op-node))
  (apply (value node) 
         (list (evaluate (left-node node))
               (evaluate (right-node node)))))

可以写:

代码语言:javascript
复制
(defmethod evaluate ((node op-node))
  (funcall (value node) 
           (evaluate (left-node node))
           (evaluate (right-node node))))

对于这个示例,您可以使用一个binop类并使用相应的函数实例化它,因为它们共享相同的evaluate方法,而不是针对每个二进制操作使用不同的子类,但这取决于您还想对节点做什么。(例如,您可能希望对每个方法都有不同的print-object方法。)

(同样,在未确定的符号上使用toplevel setfs也被认为是不好的风格,但我认为这只是为了测试和演示目的。在实际代码中,应该使用defparameterdefvar。)

票数 2
EN

Code Review用户

发布于 2012-08-24 20:30:08

代码语言:javascript
复制
(defmethod evaluate (value-node)
  (value value-node))

尝试调用(评估)。为什么要调用该方法?

票数 0
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/15039

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档