Skip to content

Instantly share code, notes, and snippets.

@tkych
Last active December 14, 2015 22:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tkych/5161126 to your computer and use it in GitHub Desktop.
Save tkych/5161126 to your computer and use it in GitHub Desktop.
Coursera, Programming-Languages, Week8, OOP vs FP, Generic function model OOP by EIEIO
;;;; Last modified : 2013-03-14 22:05:30 tkych
;; Coursera, Programming-Languages, Week8, OOP vs FP
;; Generic function model OOP by EIEIO
;; M-x ielm ; Inferior Emacs Lisp Mode
;; ELISP> (load "oop-fp-eieio-example.el")
;;====================================================================
;; Adding Operations or Variants
;;====================================================================
;; Note:
;; 1. In class name, '<' and '>' is just style convention.
;; 2. To define function make-~ is just style convention.
;; 3. Changed method name eval -> eval-exp .
(require 'eieio) ;Enhanced Implementation of Emacs Interpreted Objects
(defclass <exp> () ())
(defclass <value> (<exp>) ())
(defgeneric eval-exp (exp))
(defgeneric to-string (exp))
(defgeneric has-zero (exp))
(defclass <int> (<value>) ((i :reader i :initarg :i)))
(defun make-int (i) (make-instance '<int> :i i))
(defmethod eval-exp ((int <int>)) int)
(defmethod to-string ((int <int>)) (number-to-string (i int)))
(defmethod has-zero ((int <int>)) (zerop (i int)))
(defclass <negate> (<exp>) ((e :reader e :initarg :e)))
(defun make-negate (e) (make-instance '<negate> :e e))
(defmethod eval-exp ((n <negate>)) (make-int (- (i (eval-exp (e n))))))
(defmethod to-string ((n <negate>)) (format "(-%d)" (e n)))
(defmethod has-zero ((n <negate>)) (zerop (e n)))
(defclass <add> (<exp>)
((e1 :reader e1 :initarg :e1)
(e2 :reader e2 :initarg :e2)))
(defun make-add (e1 e2)
(make-instance '<add> :e1 e1 :e2 e2))
(defmethod eval-exp ((a <add>))
(make-int (+ (i (eval-exp (e1 a))) (i (eval-exp (e2 a))))))
(defmethod to-string ((a <add>))
(format "(%s + %s)" (to-string (e1 a)) (to-string (e2 a))))
(defmethod has-zero ((a <add>))
(or (zerop (e1 a)) (zerop (e2 a))))
;;--------------------------------------------------------------------
;; Add New Variant
;;--------------------------------------------------------------------
;; OOP is easy to add a new variant.
(defclass <mult> (<exp>)
((e1 :reader e1 :initarg :e1)
(e2 :reader e2 :initarg :e2)))
(defun make-mult (e1 e2)
(make-instance '<mult> :e1 e1 :e2 e2))
(defmethod eval-exp ((m <mult>))
(make-int (* (i (eval-exp (e1 m))) (i (eval-exp (e2 m))))))
(defmethod to-string ((m <mult>))
(format "(%s * %s)" (to-string (e1 m)) (to-string (e2 m))))
(defmethod has-zero ((m <mult>))
(or (zerop (e1 m)) (zerop (e2 m))))
;;--------------------------------------------------------------------
;; Add New Operation
;;--------------------------------------------------------------------
;; Generic function model OOP is easy to add a new operation, too.
(defgeneric no-neg-constants (exp))
(defmethod no-neg-constants ((int <int>))
(if (< (i int) 0)
(make-negate (make-int (- (i int))))
int))
(defmethod no-neg-constants ((n <negate>))
(make-negate (no-neg-constants (e n))))
(defmethod no-neg-constants ((a <add>))
(make-add (no-neg-constants (e1 a)) (no-neg-constants (e2 a))))
(defmethod no-neg-constants ((m <mult>))
(make-mult (no-neg-constants (e1 m)) (no-neg-constants (e2 m))))
;;====================================================================
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment