(index ("object" 0) ("operation" 3784) ("operation?" 5882) ("define-operation" 6023) ("define-predicate" 7213))
(def (sig (syntax "(object procedure . method-clauses)" (id object))) (p "Returns:  " (tt "object")) (p "An " (tt "OBJECT") "-expression yields an object which is prepared to handle generic operations according to the " (i "method-clauses") ". In the following description, ``the object'' refers to the value of a given " (tt "OBJECT") "-expression.") (p "Each " (i "method-clause") " should be of the form") (pre " ((operation . variables) . body)") (p (i "Operation") " is an evaluated position, and is typically a variable which evaluates to an operation, although it may be any expression.  When an operation is called with the object as its first argument, the " (i "operation") "-expressions are evaluated, and if one yields the operation being applied to the object, the corresponding " (i "method-clause") " is selected.  The operation is then performed according to the selected " (i "method-clause") ": the clause's " (i "variables") " are bound to the arguments to the operation, and its " (i "body") ", an implicit block, is evaluated.") (highlight scheme "(define op (operation #f))\n(op (object #f ((op self) 34)))      ==> 34\n(op (object #f ((op self x) x)) 55)  ==> 55") (p (i "Procedure") " may be any expression, and is evaluated at the time the " (tt "OBJECT") "-expression is evaluated.  The object, when called, simply calls the value of the " (i "procedure") " expression, passing on any arguments.  Typically " (i "procedure") " might be either a " (tt "LAMBDA") "-expression, if the object is to be callable, or it is " (tt "#f") ", which by convention means that the object is not intended to be called, the value of " (tt "#f") " being an uncallable object.") (p "In the degenerate case, where there are no method clauses, the value of") (pre " (object (lambda args . body))") (p "is indistinguishable from that of") (pre " (lambda args . body)") (p "The semantics of the " (tt "OBJECT") " and " (tt "OPERATION") " special forms can be described in terms of hypothetical primitive procedures " (tt "*OBJECT") " and " (tt "GET-HANDLER") ". These primitives do not actually exist, but are introduced here as expository aids. " (tt "*OBJECT") " takes two arguments, and returns an object which, when called, calls the object which was " (tt "*OBJECT") "'s first argument, and when given to " (tt "GET-HANDLER") " returns the object which was " (tt "*OBJECT") "'s second argument.  That is, " (tt "*OBJECT") " creates a two-component record (like a pair), " (tt "GET-HANDLER") " extracts one component, and the other component is called when the record is called.") (pre " (get-handler (*object proc handler))   ==>  handler\n ((*object proc handler) arg ...)       ==>  (proc arg ...)") (p "In addition, " (tt "GET-HANDLER") " is defined on " (i "all") " objects to return some handler, even objects not created by " (tt "*OBJECT") " (if indeed there are any such objects).") (p "Given these primitives, the following rough equivalence holds:") (pre " (object proc\n       ((op1 . args1) . body1)\n       ((op2 . args2) . body2)\n       ...\n       ((opn . argsn) . bodyn))\n ==>\n (*object proc\n        (lambda (op)\n          (switch op\n            (op1 (lambda args1 . body1)) \n            (op2 (lambda args2 . body2)) \n            ...\n            (opn (lambda argsn . bodyn))\n            (else #f))))") (p "The outer " (tt "LAMBDA") "-expression yields the object's handler; the inner " (tt "LAMBDA") "-expressions yield the methods, and the mapping from operations to methods is accomplished by the " (tt "SWITCH") "-expression Note that the syntactic positions") (pre " op1,\n op2,\n ...\n opN") (p "are evaluated positions, and the operation expressions are evaluated when an operation is applied to the object, not when the object is created."))
(def (sig (syntax "(operation default . method-clauses)" (id operation))) (p "Returns: " (tt "operation")) (p "The syntax of " (tt "OPERATION") " is the same as that of " (tt "OBJECT") ", but its semantics and application are somewhat different.  An " (tt "OPERATION") "-expression evaluates to an operation.  When called, the operation obtains a handler for its first argument, calls the handler to obtain a method, and then invokes the method.  The default method for the operation is established as being " (i "default") ".") (p "As the subject of another generic operation, an operation is an object like any other, and in this case the operation acts just as if it had been created by an " (tt "OBJECT") "-expression with the same " (i "method-clauses") ". In this way one can establish the behavior of an operation when subject to other operations, for example " (tt "SETTER") ".") (p "The following rough equivalence describes the semantics of " (tt "OPERATION") ". Some details have been omitted.") (pre " (operation default . methods)\n  ==>\n (labels ((op (object (lambda (obj . args)\n                      (let ((method ((get-handler obj) op)))\n                        (cond (method\n                               (apply method obj args))\n                              (else\n                               (apply default obj args)))))\n                    . methods)))\n op)") (p "For example:") (pre " (define op (operation (lambda (obj) 'zebu)))\n (op (object #f ((op self) 'quagga)))    -->  quagga\n (op 'eland)                              -->  zebu") (p "An operation is created, and the variable " (tt "OP") " is bound to it. The operation's default method always returns the symbol " (tt "ZEBU") ". When the operation is applied to the value of the " (tt "OBJECT") "-expression, the appropriate method is invoked, and the call to the operation yields the symbol " (tt "QUAGGA") ".  When the operation is applied to an object which doesn't handle it - the symbol " (tt "ELAND") " - the operation's default method is invoked, so the call yields the symbol " (tt "ZEBU") "."))
(def (sig (procedure "(operation? object)" (id operation?))) (p "Returns: boolean") (p "Returns true if " (i "object") " is an operation."))
(def (sig (syntax "(define-operation (variable . argument-vars) . body)" (id define-operation))) (p "Returns: undefined") (p "Defines " (i "variable") " to be an operation. The syntax is intended to be analogous to that of " (tt "DEFINE") ". The operation's default method is defined by " (i "argument-vars") " and " (i "body") ". If there is no " (i "body") ", then the operation's default method is undefined.  In this case, the " (i "argument-vars") " appear only for documentary purposes.") (pre " (define-operation (var . args) . body)\n   ==> (define var (operation (lambda args . body)))") (pre " (define-operation (var . args))\n   ==> (define var (operation undefined-effect))") (pre " [syntax] (define-settable-operation (variable . argument-vars) . body)   --> undefined") (p "Defines " (i "variable") " to be an operation, as with " (tt "DEFINE-OPERATION") ", but arranges for the operation's ``setter" (i " to be another operation, so that the operation is ``settable")) (pre " (define-settable-operation (var . args) . body)\n   ==> \n (define var\n (let ((the-setter (operation undefined-effect))) \n   (operation (lambda args . body) \n     ((setter self) the-setter))))"))
(def (sig (syntax "(define-predicate variable)" (id define-predicate))) (p "Returns: undefined") (p "Defines " (i "variable") " to be an operation which, by default, returns false.") (pre " (define-predicate var) \n   ==>\n (define-operation (var obj) #f)") (p "The intent is that particular " (tt "OBJECT") "-expressions contain clauses of the form " (tt "((variable SELF) #t)") ".  This way the operation defined by " (tt "DEFINE-PREDICATE") " may act as a type predicate that returns true only for those objects returned by such " (tt "OBJECT") "-expressions."))
