@code{(require 'object)} @ftindex object This is the Macroless Object System written by Wade Humeniuk (whumeniu@@datap.ca). Conceptual Tributes: @ref{Yasos}, MacScheme's %object, CLOS, Lack of R4RS macros. @subsection Concepts @table @asis @item OBJECT An object is an ordered association-list (by @code{eq?}) of methods (procedures). Methods can be added (@code{make-method!}), deleted (@code{unmake-method!}) and retrieved (@code{get-method}). Objects may inherit methods from other objects. The object binds to the environment it was created in, allowing closures to be used to hide private procedures and data. @item GENERIC-METHOD A generic-method associates (in terms of @code{eq?}) object's method. This allows scheme function style to be used for objects. The calling scheme for using a generic method is @code{(generic-method object param1 param2 ...)}. @item METHOD A method is a procedure that exists in the object. To use a method get-method must be called to look-up the method. Generic methods implement the get-method functionality. Methods may be added to an object associated with any scheme obj in terms of eq? @item GENERIC-PREDICATE A generic method that returns a boolean value for any scheme obj. @item PREDICATE A object's method asscociated with a generic-predicate. Returns @code{#t}. @end table @subsection Procedures @defun make-object ancestor @dots{} Returns an object. Current object implementation is a tagged vector. @var{ancestor}s are optional and must be objects in terms of object?. @var{ancestor}s methods are included in the object. Multiple @var{ancestor}s might associate the same generic-method with a method. In this case the method of the @var{ancestor} first appearing in the list is the one returned by @code{get-method}. @end defun @defun object? obj Returns boolean value whether @var{obj} was created by make-object. @end defun @defun make-generic-method exception-procedure Returns a procedure which be associated with an object's methods. If @var{exception-procedure} is specified then it is used to process non-objects. @end defun @defun make-generic-predicate Returns a boolean procedure for any scheme object. @end defun @defun make-method! object generic-method method Associates @var{method} to the @var{generic-method} in the object. The @var{method} overrides any previous association with the @var{generic-method} within the object. Using @code{unmake-method!} will restore the object's previous association with the @var{generic-method}. @var{method} must be a procedure. @end defun @defun make-predicate! object generic-preciate Makes a predicate method associated with the @var{generic-predicate}. @end defun @defun unmake-method! object generic-method Removes an object's association with a @var{generic-method} . @end defun @defun get-method object generic-method Returns the object's method associated (if any) with the @var{generic-method}. If no associated method exists an error is flagged. @end defun @subsection Examples @example (require 'object) @ftindex object (define instantiate (make-generic-method)) (define (make-instance-object . ancestors) (define self (apply make-object (map (lambda (obj) (instantiate obj)) ancestors))) (make-method! self instantiate (lambda (self) self)) self) (define who (make-generic-method)) (define imigrate! (make-generic-method)) (define emigrate! (make-generic-method)) (define describe (make-generic-method)) (define name (make-generic-method)) (define address (make-generic-method)) (define members (make-generic-method)) (define society (let () (define self (make-instance-object)) (define population '()) (make-method! self imigrate! (lambda (new-person) (if (not (eq? new-person self)) (set! population (cons new-person population))))) (make-method! self emigrate! (lambda (person) (if (not (eq? person self)) (set! population (comlist:remove-if (lambda (member) (eq? member person)) population))))) (make-method! self describe (lambda (self) (map (lambda (person) (describe person)) population))) (make-method! self who (lambda (self) (map (lambda (person) (name person)) population))) (make-method! self members (lambda (self) population)) self)) (define (make-person %name %address) (define self (make-instance-object society)) (make-method! self name (lambda (self) %name)) (make-method! self address (lambda (self) %address)) (make-method! self who (lambda (self) (name self))) (make-method! self instantiate (lambda (self) (make-person (string-append (name self) "-son-of") %address))) (make-method! self describe (lambda (self) (list (name self) (address self)))) (imigrate! self) self) @end example @subsubsection Inverter Documentation Inheritance: @lisp ::( ) @end lisp Generic-methods @lisp ::value @result{} ::value ::set-value! @result{} ::set-value! ::describe @result{} ::describe ::help ::invert ::inverter? @end lisp @subsubsection Number Documention Inheritance @lisp ::() @end lisp Slots @lisp :: @end lisp Generic Methods @lisp ::value ::set-value! @end lisp @subsubsection Inverter code @example (require 'object) @ftindex object (define value (make-generic-method (lambda (val) val))) (define set-value! (make-generic-method)) (define invert (make-generic-method (lambda (val) (if (number? val) (/ 1 val) (error "Method not supported:" val))))) (define noop (make-generic-method)) (define inverter? (make-generic-predicate)) (define describe (make-generic-method)) (define help (make-generic-method)) (define (make-number x) (define self (make-object)) (make-method! self value (lambda (this) x)) (make-method! self set-value! (lambda (this new-value) (set! x new-value))) self) (define (make-description str) (define self (make-object)) (make-method! self describe (lambda (this) str)) (make-method! self help (lambda (this) "Help not available")) self) (define (make-inverter) (let* ((self (make-object (make-number 1) (make-description "A number which can be inverted"))) ( (get-method self value))) (make-method! self invert (lambda (self) (/ 1 ( self)))) (make-predicate! self inverter?) (unmake-method! self help) (make-method! self help (lambda (self) (display "Inverter Methods:") (newline) (display " (value inverter) ==> n") (newline))) self)) ;;;; Try it out (define invert! (make-generic-method)) (define x (make-inverter)) (make-method! x invert! (lambda (x) (set-value! x (/ 1 (value x))))) (value x) @result{} 1 (set-value! x 33) @result{} undefined (invert! x) @result{} undefined (value x) @result{} 1/33 (unmake-method! x invert!) @result{} undefined (invert! x) @error{} ERROR: Method not supported: x @end example