guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Message Passing with GOOPS


From: Marko Rauhamaa
Subject: Re: Message Passing with GOOPS
Date: Thu, 25 Jun 2015 01:07:45 +0300
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux)

Michael Tiedtke <address@hidden>:

> Perhaps it's better to recreate a clean object model without 3,000
> lines of C code like GOOPS. But then GOOPS really creates the illusion
> of an object oriented environment with a MOP ...

I'd stay away from GOOPS -- it's a leap away from functional
programming, IMO.

Here's a competing, complete object system I wrote last year:

===begin simpleton.scm==================================================
(define-module (pacujo simpleton))

;;; Return the unique serial number of the object.
(define-public (serial-number object)
  (procedure-property object '%serial-number))

;(define IMPL 'HTABLE)
(define IMPL 'ALIST)
(define make-lookup-table #f)
(define associate! #f)
(define look-up #f)
(define iterate #f)

(case IMPL
  ((HTABLE)
   (set! make-lookup-table make-hash-table)
   (set! associate! hashq-set!)
   (set! look-up hashq-ref)
   (set! iterate hash-for-each-handle))
  ((ALIST)
   (set! make-lookup-table (lambda () (cons #f '())))
   (set! associate! (lambda (table key value)
                      (set-cdr! table (assq-set! (cdr table) key value))))
   (set! look-up (lambda (table key) (assq-ref (cdr table) key)))
   (set! iterate (lambda (proc table) (for-each proc (cdr table)))))
  (else
   (throw 'Huh?)))

;;; Create and return an object. Parentage must be #f, a parent object
;;; (single inheritance), or a list of parent objects (multiple
;;; inheritance).
;;;
;;; Each of the procedures must have a name and becomes a method of the
;;; object. The methods can be invoked as follows:
;;;
;;;  (define object
;;;    (let ()
;;;      (define (my-method a b c) ...)
;;;      (make-object #f my-method)))
;;;  (object #:my-method 1 2 3)
;;;
;;; Any of the procedures may also be cons cells whose car is a keyword
;;; and cdr is a function. The keyword will then be used as the method
;;; name.
(define-public (make-object parentage . procedures)
  (let ((methods (make-lookup-table)))
    (define (object method . args)
      (let ((child (procedure-property object '%child-object)))
        (if child
            (apply child method args)
            (apply-method methods method args))))
    (set-procedure-property! object '%methods methods)
    (set-procedure-property! object '%serial-number (unique))
    (inherit object parentage)
    (let register-methods ((procedures procedures))
      (cond
       ((null? procedures) object)
       ((pair? (car procedures))
        (let ((procedure (cdar procedures))
              (method (caar procedures)))
          (associate! (methods-of object) method procedure)
          (register-methods (cdr procedures))))
       (else
        (let* ((procedure (car procedures))
               (method (symbol->keyword (procedure-name procedure))))
          (associate! (methods-of object) method procedure)
          (register-methods (cdr procedures))))))))

;;; Apply the parent's method, not the child object's implementation.
(define-public (delegate parent method . args)
  (apply-method (methods-of parent) method args))

;;;
;;; DESIGN
;;;
;;; A "class" simply a constructor function that calls make-object,
;;; which populates the object structure with methods.
;;;
;;; Each object is a procedure with associated procedure properties
;;; (metainformation):
;;;
;;;  * a lookup table ('%methods) containing the method procedures (with
;;;    keywords as method keys)
;;;
;;;  * an optional child object reference ('%child-object) for virtual
;;;    method dispatching
;;;
;;;  * a unique serial number ('%serial-number) for the potential
;;;    benefit of applications (debugging, logging)
;;;

(define unique
  (let ((uniq 0))
    (lambda ()
      (set! uniq (1+ uniq))
      uniq)))

(define (inherit object parentage)
  (cond
   ((not parentage) #f)
   ((list? parentage) (inherit-multi object parentage))
   (else (inherit-single object parentage))))

(define (inherit-single object parent)
  (iterate
   (lambda (handle)
     (associate! (methods-of object) (car handle) (cdr handle)))
   (methods-of parent))
  (set-procedure-property! parent '%child-object object))

(define (inherit-multi object parents)
  (or (null? parents)
      (let ((parent (car parents)))
        (inherit-single object parent)
        (inherit-multi object (cdr parents)))))

(define (methods-of object)
  (procedure-property object '%methods))

(define (apply-method methods method args)
  (let ((procedure (look-up methods method)))
    (if procedure
        (apply procedure args)
        (error "No such method" method))))
===end simpleton.scm====================================================

All you need is the make-object function.


Marko



reply via email to

[Prev in Thread] Current Thread [Next in Thread]