SLIB


Table of Contents


The Library System

Feature

SLIB denotes features by symbols. SLIB maintains a list of features supported by the Scheme session. The set of features provided by a session may change over time. Some features are properties of the Scheme implementation being used. The following features detail what sort of numbers are available from an implementation.

Other features correspond to the presence of sets of Scheme procedures or syntax (macros).

Function: provided? feature
Returns #t if feature is supported by the current Scheme session.

Procedure: provide feature
Informs SLIB that feature is supported. Henceforth (provided? feature) will return #t.
(provided? 'foo)    => #f
(provide 'foo)
(provided? 'foo)    => #t

Requesting Features

SLIB creates and maintains a catalog mapping features to locations of files introducing procedures and syntax denoted by those features.

At the beginning of each section of this manual, there is a line like (require 'feature). The Scheme files comprising SLIB are cataloged so that these feature names map to the corresponding files.

SLIB provides a form, require, which loads the files providing the requested feature.

Procedure: require feature

The catalog can also be queried using require:feature->path.

Function: require:feature->path feature

Library Catalogs

At the start of a session no catalog is present, but is created with the first catalog inquiry (such as (require 'random)). Several sources of catalog information are combined to produce the catalog:

Catalog files consist of one or more association lists. In the circumstance where a feature symbol appears in more than one list, the latter list's association is retrieved. Here are the supported formats for elements of catalog lists:

(feature . <symbol>)
Redirects to the feature named <symbol>.
(feature . "<path>")
Loads file <path>.
(feature source "<path>")
slib:loads the Scheme source file <path>.
(feature compiled "<path>" ...)
slib:load-compileds the files <path> ....

The various macro styles first require the named macro package, then just load <path> or load-and-macro-expand <path> as appropriate for the implementation.

(feature defmacro "<path>")
defmacro:loads the Scheme source file <path>.
(feature macro-by-example "<path>")
defmacro:loads the Scheme source file <path>.
(feature macro "<path>")
macro:loads the Scheme source file <path>.
(feature macros-that-work "<path>")
macro:loads the Scheme source file <path>.
(feature syntax-case "<path>")
macro:loads the Scheme source file <path>.
(feature syntactic-closures "<path>")
macro:loads the Scheme source file <path>.

Here is an example of a `usercat' catalog. A Program in this directory can invoke the `run' feature with (require 'run).

;;; "usercat": SLIB catalog additions for SIMSYNCH.     -*-scheme-*-

(
 (simsynch      . "../synch/simsynch.scm")
 (run           . "../synch/run.scm")
 (schlep        . "schlep.scm")
)

Catalog Compilation

SLIB combines the catalog information which doesn't vary per user into the file `slibcat' in the implementation-vicinity. Therefore `slibcat' needs change only when new software is installed or compiled. Because the actual pathnames of files can differ from installation to installation, SLIB builds a separate catalog for each implementation it is used with.

The definition of *SLIB-VERSION* in SLIB file `require.scm' is checked against the catalog association of *SLIB-VERSION* to ascertain when versions have changed. I recommend that the definition of *SLIB-VERSION* be changed whenever the library is changed. If multiple implementations of Scheme use SLIB, remember that recompiling one `slibcat' will fix only that implementation's catalog.

The compilation scripts of Scheme implementations which work with SLIB can automatically trigger catalog compilation by deleting `slibcat' or by invoking a special form of require:

Procedure: require 'new-catalog
This will load `mklibcat', which compiles and writes a new `slibcat'.

Another special form of require erases SLIB's catalog, forcing it to be reloaded the next time the catalog is queried.

Procedure: require #f
Removes SLIB's catalog information. This should be done before saving an executable image so that, when restored, its catalog will be loaded afresh.

Each file in the table below is descibed in terms of its file-system independent vicinity (see section Vicinity). The entries of a catalog in the table override those of catalogs above it in the table.

implementation-vicinity `slibcat'
This file contains the associations for the packages comprising SLIB, the `implcat' and the `sitecat's. The associations in the other catalogs override those of the standard catalog.
library-vicinity `mklibcat.scm'
creates `slibcat'.
library-vicinity `sitecat'
This file contains the associations specific to an SLIB installation.
implementation-vicinity `implcat'
This file contains the associations specific to an implementation of Scheme. Different implementations of Scheme should have different implementation-vicinity.
implementation-vicinity `mkimpcat.scm'
if present, creates `implcat'.
implementation-vicinity `sitecat'
This file contains the associations specific to a Scheme implementation installation.
home-vicinity `homecat'
This file contains the associations specific to an SLIB user.
user-vicinity `usercat'
This file contains associations effecting only those sessions whose working directory is user-vicinity.

Built-in Support

The procedures described in these sections are supported by all implementations as part of the `*.init' files or by `require.scm'.

Require

Variable: *features*
Is a list of symbols denoting features supported in this implementation. *features* can grow as modules are required. *features* must be defined by all implementations (see section Porting).

Here are features which SLIB (`require.scm') adds to *features* when appropriate.

For each item, (provided? 'feature) will return #t if that feature is available, and #f if not.

Variable: *modules*
Is a list of pathnames denoting files which have been loaded.

Variable: *catalog*
Is an association list of features (symbols) and pathnames which will supply those features. The pathname can be either a string or a pair. If pathname is a pair then the first element should be a macro feature symbol, source, or compiled. The cdr of the pathname should be either a string or a list.

In the following functions if the argument feature is not a symbol it is assumed to be a pathname.

Function: provided? feature
Returns #t if feature is a member of *features* or *modules* or if feature is supported by a file already loaded and #f otherwise.

Procedure: require feature
feature is a symbol. If (provided? feature) is true require returns. Otherwise, if (assq feature *catalog*) is not #f, the associated files will be loaded and (provided? feature) will henceforth return #t. An unspecified value is returned. If feature is not found in *catalog*, then an error is signaled.

Procedure: require pathname
pathname is a string. If pathname has not already been given as an argument to require, pathname is loaded. An unspecified value is returned.

Procedure: provide feature
Assures that feature is contained in *features* if feature is a symbol and *modules* otherwise.

Function: require:feature->path feature
Returns #t if feature is a member of *features* or *modules* or if feature is supported by a file already loaded. Returns a path if one was found in *catalog* under the feature name, and #f otherwise. The path can either be a string suitable as an argument to load or a pair as described above for *catalog*.

Vicinity

A vicinity is a descriptor for a place in the file system. Vicinities hide from the programmer the concepts of host, volume, directory, and version. Vicinities express only the concept of a file environment where a file name can be resolved to a file in a system independent manner. Vicinities can even be used on flat file systems (which have no directory structure) by having the vicinity express constraints on the file name. On most systems a vicinity would be a string. All of these procedures are file system dependent.

These procedures are provided by all implementations.

Function: make-vicinity path
Returns the vicinity of path for use by in-vicinity.

Function: program-vicinity
Returns the vicinity of the currently loading Scheme code. For an interpreter this would be the directory containing source code. For a compiled system (with multiple files) this would be the directory where the object or executable files are. If no file is currently loading it the result is undefined. Warning: program-vicinity can return incorrect values if your program escapes back into a load.

Function: library-vicinity
Returns the vicinity of the shared Scheme library.

Function: implementation-vicinity
Returns the vicinity of the underlying Scheme implementation. This vicinity will likely contain startup code and messages and a compiler.

Function: user-vicinity
Returns the vicinity of the current directory of the user. On most systems this is `""' (the empty string).

Function: home-vicinity
Returns the vicinity of the user's HOME directory, the directory which typically contains files which customize a computer environment for a user. If scheme is running without a user (eg. a daemon) or if this concept is meaningless for the platform, then home-vicinity returns #f.

Function: in-vicinity vicinity filename
Returns a filename suitable for use by slib:load, slib:load-source, slib:load-compiled, open-input-file, open-output-file, etc. The returned filename is filename in vicinity. in-vicinity should allow filename to override vicinity when filename is an absolute pathname and vicinity is equal to the value of (user-vicinity). The behavior of in-vicinity when filename is absolute and vicinity is not equal to the value of (user-vicinity) is unspecified. For most systems in-vicinity can be string-append.

Function: sub-vicinity vicinity name
Returns the vicinity of vicinity restricted to name. This is used for large systems where names of files in subsystems could conflict. On systems with directory structure sub-vicinity will return a pathname of the subdirectory name of vicinity.

Configuration

These constants and procedures describe characteristics of the Scheme and underlying operating system. They are provided by all implementations.

Constant: char-code-limit
An integer 1 larger that the largest value which can be returned by char->integer.

Constant: most-positive-fixnum
In implementations which support integers of practically unlimited size, most-positive-fixnum is a large exact integer within the range of exact integers that may result from computing the length of a list, vector, or string.

In implementations which do not support integers of practically unlimited size, most-positive-fixnum is the largest exact integer that may result from computing the length of a list, vector, or string.

Constant: slib:tab
The tab character.

Constant: slib:form-feed
The form-feed character.

Function: software-type
Returns a symbol denoting the generic operating system type. For instance, unix, vms, macos, amiga, or ms-dos.

Function: slib:report-version
Displays the versions of SLIB and the underlying Scheme implementation and the name of the operating system. An unspecified value is returned.
(slib:report-version) => slib "2c7" on scm "5b1" on unix 

Function: slib:report
Displays the information of (slib:report-version) followed by almost all the information neccessary for submitting a problem report. An unspecified value is returned.

Function: slib:report #t
provides a more verbose listing.

Function: slib:report filename
Writes the report to file `filename'.
(slib:report)
=>
slib "2c7" on scm "5b1" on unix 
(implementation-vicinity) is "/home/jaffer/scm/" 
(library-vicinity) is "/home/jaffer/slib/" 
(scheme-file-suffix) is ".scm" 
loaded *features* : 
        trace alist qp sort
        common-list-functions macro values getopt
        compiled
implementation *features* : 
        bignum complex real rational
        inexact vicinity ed getenv
        tmpnam abort transcript with-file
        ieee-p1178 rev4-report rev4-optional-procedures hash
        object-hash delay eval dynamic-wind
        multiarg-apply multiarg/and- logical defmacro
        string-port source current-time record
        rev3-procedures rev2-procedures sun-dl string-case
        array dump char-ready? full-continuation
        system
implementation *catalog* : 
        (i/o-extensions compiled "/home/jaffer/scm/ioext.so") 
        ... 

Input/Output

These procedures are provided by all implementations.

Procedure: file-exists? filename
Returns #t if the specified file exists. Otherwise, returns #f. If the underlying implementation does not support this feature then #f is always returned.

Procedure: delete-file filename
Deletes the file specified by filename. If filename can not be deleted, #f is returned. Otherwise, #t is returned.

Procedure: tmpnam
Returns a pathname for a file which will likely not be used by any other process. Successive calls to (tmpnam) will return different pathnames.

Procedure: current-error-port
Returns the current port to which diagnostic and error output is directed.

Procedure: force-output
Procedure: force-output port
Forces any pending output on port to be delivered to the output device and returns an unspecified value. The port argument may be omitted, in which case it defaults to the value returned by (current-output-port).

Procedure: output-port-width
Procedure: output-port-width port

Returns the width of port, which defaults to (current-output-port) if absent. If the width cannot be determined 79 is returned.

Procedure: output-port-height
Procedure: output-port-height port

Returns the height of port, which defaults to (current-output-port) if absent. If the height cannot be determined 24 is returned.

Legacy

These procedures are provided by all implementations.

Function: identity x
identity returns its argument.

Example:

(identity 3)
   => 3
(identity '(foo bar))
   => (foo bar)
(map identity lst)
   == (copy-list lst)

The following procedures were present in Scheme until R4RS (see section `Language changes' in Revised(4) Scheme). They are provided by all SLIB implementations.

Constant: t
Derfined as #t.

Constant: nil
Defined as #f.

Function: last-pair l
Returns the last pair in the list l. Example:
(last-pair (cons 1 2))
   => (1 . 2)
(last-pair '(1 2))
   => (2)
    == (cons 2 '())

System

These procedures are provided by all implementations.

Procedure: slib:load-source name
Loads a file of Scheme source code from name with the default filename extension used in SLIB. For instance if the filename extension used in SLIB is `.scm' then (slib:load-source "foo") will load from file `foo.scm'.

Procedure: slib:load-compiled name
On implementations which support separtely loadable compiled modules, loads a file of compiled code from name with the implementation's filename extension for compiled code appended.

Procedure: slib:load name
Loads a file of Scheme source or compiled code from name with the appropriate suffixes appended. If both source and compiled code are present with the appropriate names then the implementation will load just one. It is up to the implementation to choose which one will be loaded.

If an implementation does not support compiled code then slib:load will be identical to slib:load-source.

Procedure: slib:eval obj
eval returns the value of obj evaluated in the current top level environment. section Eval provides a more general evaluation facility.

Procedure: slib:eval-load filename eval
filename should be a string. If filename names an existing file, the Scheme source code expressions and definitions are read from the file and eval called with them sequentially. The slib:eval-load procedure does not affect the values returned by current-input-port and current-output-port.

Procedure: slib:warn arg1 arg2 ...
Outputs a warning message containing the arguments.

Procedure: slib:error arg1 arg2 ...
Outputs an error message containing the arguments, aborts evaluation of the current form and responds in a system dependent way to the error. Typical responses are to abort the program or to enter a read-eval-print loop.

Procedure: slib:exit n
Procedure: slib:exit
Exits from the Scheme session returning status n to the system. If n is omitted or #t, a success status is returned to the system (if possible). If n is #f a failure is returned to the system (if possible). If n is an integer, then n is returned to the system (if possible). If the Scheme session cannot exit an unspecified value is returned from slib:exit.

About this manual

Scheme Syntax Extension Packages

Defmacro

Defmacros are supported by all implementations.

Function: gentemp
Returns a new (interned) symbol each time it is called. The symbol names are implementation-dependent
(gentemp) => scm:G0
(gentemp) => scm:G1

Function: defmacro:eval e
Returns the slib:eval of expanding all defmacros in scheme expression e.

Function: defmacro:load filename
filename should be a string. If filename names an existing file, the defmacro:load procedure reads Scheme source code expressions and definitions from the file and evaluates them sequentially. These source code expressions and definitions may contain defmacro definitions. The macro:load procedure does not affect the values returned by current-input-port and current-output-port.

Function: defmacro? sym
Returns #t if sym has been defined by defmacro, #f otherwise.

Function: macroexpand-1 form
Function: macroexpand form
If form is a macro call, macroexpand-1 will expand the macro call once and return it. A form is considered to be a macro call only if it is a cons whose car is a symbol for which a defmacr has been defined.

macroexpand is similar to macroexpand-1, but repeatedly expands form until it is no longer a macro call.

Macro: defmacro name lambda-list form ...
When encountered by defmacro:eval, defmacro:macroexpand*, or defmacro:load defines a new macro which will henceforth be expanded when encountered by defmacro:eval, defmacro:macroexpand*, or defmacro:load.

Defmacroexpand

(require 'defmacroexpand)

Function: defmacro:expand* e
Returns the result of expanding all defmacros in scheme expression e.

R4RS Macros

(require 'macro) is the appropriate call if you want R4RS high-level macros but don't care about the low level implementation. If an SLIB R4RS macro implementation is already loaded it will be used. Otherwise, one of the R4RS macros implemetations is loaded.

The SLIB R4RS macro implementations support the following uniform interface:

Function: macro:expand sexpression
Takes an R4RS expression, macro-expands it, and returns the result of the macro expansion.

Function: macro:eval sexpression
Takes an R4RS expression, macro-expands it, evals the result of the macro expansion, and returns the result of the evaluation.

Procedure: macro:load filename
filename should be a string. If filename names an existing file, the macro:load procedure reads Scheme source code expressions and definitions from the file and evaluates them sequentially. These source code expressions and definitions may contain macro definitions. The macro:load procedure does not affect the values returned by current-input-port and current-output-port.

Macro by Example

(require 'macro-by-example)

A vanilla implementation of Macro by Example (Eugene Kohlbecker, R4RS) by Dorai Sitaram, (dorai@cs.rice.edu) using defmacro.

Caveat

These macros are not referentially transparent (see section `Macros' in Revised(4) Scheme). Lexically scoped macros (i.e., let-syntax and letrec-syntax) are not supported. In any case, the problem of referential transparency gains poignancy only when let-syntax and letrec-syntax are used. So you will not be courting large-scale disaster unless you're using system-function names as local variables with unintuitive bindings that the macro can't use. However, if you must have the full r4rs macro functionality, look to the more featureful (but also more expensive) versions of syntax-rules available in slib section Macros That Work, section Syntactic Closures, and section Syntax-Case Macros.

Macro: define-syntax keyword transformer-spec
The keyword is an identifier, and the transformer-spec should be an instance of syntax-rules.

The top-level syntactic environment is extended by binding the keyword to the specified transformer.

(define-syntax let*
  (syntax-rules ()
    ((let* () body1 body2 ...)
     (let () body1 body2 ...))
    ((let* ((name1 val1) (name2 val2) ...)
       body1 body2 ...)
     (let ((name1 val1))
       (let* (( name2 val2) ...)
         body1 body2 ...)))))

Macro: syntax-rules literals syntax-rule ...
literals is a list of identifiers, and each syntax-rule should be of the form

(pattern template)

where the pattern and template are as in the grammar above.

An instance of syntax-rules produces a new macro transformer by specifying a sequence of hygienic rewrite rules. A use of a macro whose keyword is associated with a transformer specified by syntax-rules is matched against the patterns contained in the syntax-rules, beginning with the leftmost syntax-rule. When a match is found, the macro use is trancribed hygienically according to the template.

Each pattern begins with the keyword for the macro. This keyword is not involved in the matching and is not considered a pattern variable or literal identifier.

Macros That Work

(require 'macros-that-work)

Macros That Work differs from the other R4RS macro implementations in that it does not expand derived expression types to primitive expression types.

Function: macro:expand expression
Function: macwork:expand expression
Takes an R4RS expression, macro-expands it, and returns the result of the macro expansion.

Function: macro:eval expression
Function: macwork:eval expression
macro:eval returns the value of expression in the current top level environment. expression can contain macro definitions. Side effects of expression will affect the top level environment.

Procedure: macro:load filename
Procedure: macwork:load filename
filename should be a string. If filename names an existing file, the macro:load procedure reads Scheme source code expressions and definitions from the file and evaluates them sequentially. These source code expressions and definitions may contain macro definitions. The macro:load procedure does not affect the values returned by current-input-port and current-output-port.

References:

The Revised^4 Report on the Algorithmic Language Scheme Clinger and Rees [editors]. To appear in LISP Pointers. Also available as a technical report from the University of Oregon, MIT AI Lab, and Cornell.

Macros That Work. Clinger and Rees. POPL '91.

The supported syntax differs from the R4RS in that vectors are allowed as patterns and as templates and are not allowed as pattern or template data.

transformer spec  ==>  (syntax-rules literals rules)

rules  ==>  ()
         |  (rule . rules)

rule  ==>  (pattern template)

pattern  ==>  pattern_var      ; a symbol not in literals
           |  symbol           ; a symbol in literals
           |  ()
           |  (pattern . pattern)
           |  (ellipsis_pattern)
           |  #(pattern*)                     ; extends R4RS
           |  #(pattern* ellipsis_pattern)    ; extends R4RS
           |  pattern_datum

template  ==>  pattern_var
            |  symbol
            |  ()
            |  (template2 . template2)
            |  #(template*)                   ; extends R4RS
            |  pattern_datum

template2  ==>  template
             |  ellipsis_template

pattern_datum  ==>  string                    ; no vector
                 |  character
                 |  boolean
                 |  number

ellipsis_pattern  ==> pattern ...

ellipsis_template  ==>  template ...

pattern_var  ==>  symbol   ; not in literals

literals  ==>  ()
            |  (symbol . literals)

Definitions

Scope of an ellipsis
Within a pattern or template, the scope of an ellipsis (...) is the pattern or template that appears to its left.
Rank of a pattern variable
The rank of a pattern variable is the number of ellipses within whose scope it appears in the pattern.
Rank of a subtemplate
The rank of a subtemplate is the number of ellipses within whose scope it appears in the template.
Template rank of an occurrence of a pattern variable
The template rank of an occurrence of a pattern variable within a template is the rank of that occurrence, viewed as a subtemplate.
Variables bound by a pattern
The variables bound by a pattern are the pattern variables that appear within it.
Referenced variables of a subtemplate
The referenced variables of a subtemplate are the pattern variables that appear within it.
Variables opened by an ellipsis template
The variables opened by an ellipsis template are the referenced pattern variables whose rank is greater than the rank of the ellipsis template.

Restrictions

No pattern variable appears more than once within a pattern.

For every occurrence of a pattern variable within a template, the template rank of the occurrence must be greater than or equal to the pattern variable's rank.

Every ellipsis template must open at least one variable.

For every ellipsis template, the variables opened by an ellipsis template must all be bound to sequences of the same length.

The compiled form of a rule is

rule  ==>  (pattern template inserted)

pattern  ==>  pattern_var
           |  symbol
           |  ()
           |  (pattern . pattern)
           |  ellipsis_pattern
           |  #(pattern)
           |  pattern_datum

template  ==>  pattern_var
            |  symbol
            |  ()
            |  (template2 . template2)
            |  #(pattern)
            |  pattern_datum

template2  ==>  template
             |  ellipsis_template

pattern_datum  ==>  string
                 |  character
                 |  boolean
                 |  number

pattern_var  ==>  #(V symbol rank)

ellipsis_pattern  ==>  #(E pattern pattern_vars)

ellipsis_template  ==>  #(E template pattern_vars)

inserted  ==>  ()
            |  (symbol . inserted)

pattern_vars  ==>  ()
                |  (pattern_var . pattern_vars)

rank  ==>  exact non-negative integer

where V and E are unforgeable values.

The pattern variables associated with an ellipsis pattern are the variables bound by the pattern, and the pattern variables associated with an ellipsis template are the variables opened by the ellipsis template.

If the template contains a big chunk that contains no pattern variables or inserted identifiers, then the big chunk will be copied unnecessarily. That shouldn't matter very often.

Syntactic Closures

(require 'syntactic-closures)

Function: macro:expand expression
Function: synclo:expand expression
Returns scheme code with the macros and derived expression types of expression expanded to primitive expression types.

Function: macro:eval expression
Function: synclo:eval expression
macro:eval returns the value of expression in the current top level environment. expression can contain macro definitions. Side effects of expression will affect the top level environment.

Procedure: macro:load filename
Procedure: synclo:load filename
filename should be a string. If filename names an existing file, the macro:load procedure reads Scheme source code expressions and definitions from the file and evaluates them sequentially. These source code expressions and definitions may contain macro definitions. The macro:load procedure does not affect the values returned by current-input-port and current-output-port.

Syntactic Closure Macro Facility

A Syntactic Closures Macro Facility by Chris Hanson 9 November 1991

This document describes syntactic closures, a low-level macro facility for the Scheme programming language. The facility is an alternative to the low-level macro facility described in the Revised^4 Report on Scheme. This document is an addendum to that report.

The syntactic closures facility extends the BNF rule for transformer spec to allow a new keyword that introduces a low-level macro transformer:

transformer spec := (transformer expression)

Additionally, the following procedures are added:

make-syntactic-closure
capture-syntactic-environment
identifier?
identifier=?

The description of the facility is divided into three parts. The first part defines basic terminology. The second part describes how macro transformers are defined. The third part describes the use of identifiers, which extend the syntactic closure mechanism to be compatible with syntax-rules.

Terminology

This section defines the concepts and data types used by the syntactic closures facility.

Transformer Definition

This section describes the transformer special form and the procedures make-syntactic-closure and capture-syntactic-environment.

Syntax: transformer expression

Syntax: It is an error if this syntax occurs except as a transformer spec.

Semantics: The expression is evaluated in the standard transformer environment to yield a macro transformer as described below. This macro transformer is bound to a macro keyword by the special form in which the transformer expression appears (for example, let-syntax).

A macro transformer is a procedure that takes two arguments, a form and a syntactic environment, and returns a new form. The first argument, the input form, is the form in which the macro keyword occurred. The second argument, the usage environment, is the syntactic environment in which the input form occurred. The result of the transformer, the output form, is automatically closed in the transformer environment, which is the syntactic environment in which the transformer expression occurred.

For example, here is a definition of a push macro using syntax-rules:

(define-syntax  push
  (syntax-rules ()
    ((push item list)
     (set! list (cons item list)))))

Here is an equivalent definition using transformer:

(define-syntax push
  (transformer
   (lambda (exp env)
     (let ((item
            (make-syntactic-closure env '() (cadr exp)))
           (list
            (make-syntactic-closure env '() (caddr exp))))
       `(set! ,list (cons ,item ,list))))))

In this example, the identifiers set! and cons are closed in the transformer environment, and thus will not be affected by the meanings of those identifiers in the usage environment env.

Some macros may be non-hygienic by design. For example, the following defines a loop macro that implicitly binds exit to an escape procedure. The binding of exit is intended to capture free references to exit in the body of the loop, so exit must be left free when the body is closed:

(define-syntax loop
  (transformer
   (lambda (exp env)
     (let ((body (cdr exp)))
       `(call-with-current-continuation
         (lambda (exit)
           (let f ()
             ,@(map (lambda  (exp)
                       (make-syntactic-closure env '(exit)
                                               exp))
                     body)
             (f))))))))

To assign meanings to the identifiers in a form, use make-syntactic-closure to close the form in a syntactic environment.

Function: make-syntactic-closure environment free-names form

environment must be a syntactic environment, free-names must be a list of identifiers, and form must be a form. make-syntactic-closure constructs and returns a syntactic closure of form in environment, which can be used anywhere that form could have been used. All the identifiers used in form, except those explicitly excepted by free-names, obtain their meanings from environment.

Here is an example where free-names is something other than the empty list. It is instructive to compare the use of free-names in this example with its use in the loop example above: the examples are similar except for the source of the identifier being left free.

(define-syntax let1
  (transformer
   (lambda (exp env)
     (let ((id (cadr exp))
           (init (caddr exp))
           (exp (cadddr exp)))
       `((lambda (,id)
           ,(make-syntactic-closure env (list id) exp))
         ,(make-syntactic-closure env '() init))))))

let1 is a simplified version of let that only binds a single identifier, and whose body consists of a single expression. When the body expression is syntactically closed in its original syntactic environment, the identifier that is to be bound by let1 must be left free, so that it can be properly captured by the lambda in the output form.

To obtain a syntactic environment other than the usage environment, use capture-syntactic-environment.

Function: capture-syntactic-environment procedure

capture-syntactic-environment returns a form that will, when transformed, call procedure on the current syntactic environment. procedure should compute and return a new form to be transformed, in that same syntactic environment, in place of the form.

An example will make this clear. Suppose we wanted to define a simple loop-until keyword equivalent to

(define-syntax loop-until
  (syntax-rules ()
    ((loop-until id init test return step)
     (letrec ((loop
               (lambda (id)
                 (if test return (loop step)))))
       (loop init)))))

The following attempt at defining loop-until has a subtle bug:

(define-syntax loop-until
  (transformer
   (lambda (exp env)
     (let ((id (cadr exp))
           (init (caddr exp))
           (test (cadddr exp))
           (return (cadddr (cdr exp)))
           (step (cadddr (cddr exp)))
           (close
            (lambda (exp free)
              (make-syntactic-closure env free exp))))
       `(letrec ((loop
                  (lambda (,id)
                    (if ,(close test (list id))
                        ,(close return (list id))
                        (loop ,(close step (list id)))))))
          (loop ,(close init '())))))))

This definition appears to take all of the proper precautions to prevent unintended captures. It carefully closes the subexpressions in their original syntactic environment and it leaves the id identifier free in the test, return, and step expressions, so that it will be captured by the binding introduced by the lambda expression. Unfortunately it uses the identifiers if and loop within that lambda expression, so if the user of loop-until just happens to use, say, if for the identifier, it will be inadvertently captured.

The syntactic environment that if and loop want to be exposed to is the one just outside the lambda expression: before the user's identifier is added to the syntactic environment, but after the identifier loop has been added. capture-syntactic-environment captures exactly that environment as follows:

(define-syntax loop-until
  (transformer
   (lambda (exp env)
     (let ((id (cadr exp))
           (init (caddr exp))
           (test (cadddr exp))
           (return (cadddr (cdr exp)))
           (step (cadddr (cddr exp)))
           (close
            (lambda (exp free)
              (make-syntactic-closure env free exp))))
       `(letrec ((loop
                  ,(capture-syntactic-environment
                    (lambda (env)
                      `(lambda (,id)
                         (,(make-syntactic-closure env '() `if)
                          ,(close test (list id))
                          ,(close return (list id))
                          (,(make-syntactic-closure env '()
                                                    `loop)
                           ,(close step (list id)))))))))
          (loop ,(close init '())))))))

In this case, having captured the desired syntactic environment, it is convenient to construct syntactic closures of the identifiers if and the loop and use them in the body of the lambda.

A common use of capture-syntactic-environment is to get the transformer environment of a macro transformer:

(transformer
 (lambda (exp env)
   (capture-syntactic-environment
    (lambda (transformer-env)
      ...))))

Identifiers

This section describes the procedures that create and manipulate identifiers. Previous syntactic closure proposals did not have an identifier data type -- they just used symbols. The identifier data type extends the syntactic closures facility to be compatible with the high-level syntax-rules facility.

As discussed earlier, an identifier is either a symbol or an alias. An alias is implemented as a syntactic closure whose form is an identifier:

(make-syntactic-closure env '() 'a)
   => an alias

Aliases are implemented as syntactic closures because they behave just like syntactic closures most of the time. The difference is that an alias may be bound to a new value (for example by lambda or let-syntax); other syntactic closures may not be used this way. If an alias is bound, then within the scope of that binding it is looked up in the syntactic environment just like any other identifier.

Aliases are used in the implementation of the high-level facility syntax-rules. A macro transformer created by syntax-rules uses a template to generate its output form, substituting subforms of the input form into the template. In a syntactic closures implementation, all of the symbols in the template are replaced by aliases closed in the transformer environment, while the output form itself is closed in the usage environment. This guarantees that the macro transformation is hygienic, without requiring the transformer to know the syntactic roles of the substituted input subforms.

Function: identifier? object
Returns #t if object is an identifier, otherwise returns #f. Examples:
(identifier? 'a)
   => #t
(identifier? (make-syntactic-closure env '() 'a))
   => #t
(identifier? "a")
   => #f
(identifier? #\a)
   => #f
(identifier? 97)
   => #f
(identifier? #f)
   => #f
(identifier? '(a))
   => #f
(identifier? '#(a))
   => #f

The predicate eq? is used to determine if two identifers are "the same". Thus eq? can be used to compare identifiers exactly as it would be used to compare symbols. Often, though, it is useful to know whether two identifiers "mean the same thing". For example, the cond macro uses the symbol else to identify the final clause in the conditional. A macro transformer for cond cannot just look for the symbol else, because the cond form might be the output of another macro transformer that replaced the symbol else with an alias. Instead the transformer must look for an identifier that "means the same thing" in the usage environment as the symbol else means in the transformer environment.

Function: identifier=? environment1 identifier1 environment2 identifier2
environment1 and environment2 must be syntactic environments, and identifier1 and identifier2 must be identifiers. identifier=? returns #t if the meaning of identifier1 in environment1 is the same as that of identifier2 in environment2, otherwise it returns #f. Examples:
(let-syntax
    ((foo
      (transformer
       (lambda (form env)
         (capture-syntactic-environment
          (lambda (transformer-env)
            (identifier=? transformer-env 'x env 'x)))))))
  (list (foo)
        (let ((x 3))
          (foo))))
   => (#t #f)
(let-syntax ((bar foo))
  (let-syntax
      ((foo
        (transformer
         (lambda (form env)
           (capture-syntactic-environment
            (lambda (transformer-env)
              (identifier=? transformer-env 'foo
                            env (cadr form))))))))
    (list (foo foo)
          (foobar))))
   => (#f #t)

Acknowledgements

The syntactic closures facility was invented by Alan Bawden and Jonathan Rees. The use of aliases to implement syntax-rules was invented by Alan Bawden (who prefers to call them synthetic names). Much of this proposal is derived from an earlier proposal by Alan Bawden.

Syntax-Case Macros

(require 'syntax-case)

Function: macro:expand expression
Function: syncase:expand expression
Returns scheme code with the macros and derived expression types of expression expanded to primitive expression types.

Function: macro:eval expression
Function: syncase:eval expression
macro:eval returns the value of expression in the current top level environment. expression can contain macro definitions. Side effects of expression will affect the top level environment.

Procedure: macro:load filename
Procedure: syncase:load filename
filename should be a string. If filename names an existing file, the macro:load procedure reads Scheme source code expressions and definitions from the file and evaluates them sequentially. These source code expressions and definitions may contain macro definitions. The macro:load procedure does not affect the values returned by current-input-port and current-output-port.

This is version 2.1 of syntax-case, the low-level macro facility proposed and implemented by Robert Hieb and R. Kent Dybvig.

This version is further adapted by Harald Hanche-Olsen <hanche@imf.unit.no> to make it compatible with, and easily usable with, SLIB. Mainly, these adaptations consisted of:

If you wish, you can see exactly what changes were done by reading the shell script in the file `syncase.sh'.

The two PostScript files were omitted in order to not burden the SLIB distribution with them. If you do intend to use syntax-case, however, you should get these files and print them out on a PostScript printer. They are available with the original syntax-case distribution by anonymous FTP in `cs.indiana.edu:/pub/scheme/syntax-case'.

In order to use syntax-case from an interactive top level, execute:

(require 'syntax-case)
(require 'repl)
(repl:top-level macro:eval)

See the section Repl (see section Repl) for more information.

To check operation of syntax-case get `cs.indiana.edu:/pub/scheme/syntax-case', and type

(require 'syntax-case)
(syncase:sanity-check)

Beware that syntax-case takes a long time to load -- about 20s on a SPARCstation SLC (with SCM) and about 90s on a Macintosh SE/30 (with Gambit).

Notes

All R4RS syntactic forms are defined, including delay. Along with delay are simple definitions for make-promise (into which delay expressions expand) and force.

syntax-rules and with-syntax (described in TR356) are defined.

syntax-case is actually defined as a macro that expands into calls to the procedure syntax-dispatch and the core form syntax-lambda; do not redefine these names.

Several other top-level bindings not documented in TR356 are created:

The syntax of define has been extended to allow (define id), which assigns id to some unspecified value.

We have attempted to maintain R4RS compatibility where possible. The incompatibilities should be confined to `hooks.ss'. Please let us know if there is some incompatibility that is not flagged as such.

Send bug reports, comments, suggestions, and questions to Kent Dybvig (dyb@iuvax.cs.indiana.edu).

Note from maintainer

Included with the syntax-case files was `structure.scm' which defines a macro define-structure. There is no documentation for this macro and it is not used by any code in SLIB.

Fluid-Let

(require 'fluid-let)

Syntax: fluid-let (bindings ...) forms...
(fluid-let ((variable init) ...)
   expression expression ...)

The inits are evaluated in the current environment (in some unspecified order), the current values of the variables are saved, the results are assigned to the variables, the expressions are evaluated sequentially in the current environment, the variables are restored to their original values, and the value of the last expression is returned.

The syntax of this special form is similar to that of let, but fluid-let temporarily rebinds existing variables. Unlike let, fluid-let creates no new bindings; instead it assigns the values of each init to the binding (determined by the rules of lexical scoping) of its corresponding variable.

Yasos

(require 'oop) or (require 'yasos)

`Yet Another Scheme Object System' is a simple object system for Scheme based on the paper by Norman Adams and Jonathan Rees: Object Oriented Programming in Scheme, Proceedings of the 1988 ACM Conference on LISP and Functional Programming, July 1988 [ACM #552880].

Another reference is:

Ken Dickey. Scheming with Objects AI Expert Volume 7, Number 10 (October 1992), pp. 24-33.

Terms

Object
Any Scheme data object.
Instance
An instance of the OO system; an object.
Operation
A method.
Notes:
The object system supports multiple inheritance. An instance can inherit from 0 or more ancestors. In the case of multiple inherited operations with the same identity, the operation used is that from the first ancestor which contains it (in the ancestor let). An operation may be applied to any Scheme data object--not just instances. As code which creates instances is just code, there are no classes and no meta-anything. Method dispatch is by a procedure call a la CLOS rather than by send syntax a la Smalltalk.
Disclaimer:
There are a number of optimizations which can be made. This implementation is expository (although performance should be quite reasonable). See the L&FP paper for some suggestions.

Interface

Syntax: define-operation (opname self arg ...) default-body
Defines a default behavior for data objects which don't handle the operation opname. The default behavior (for an empty default-body) is to generate an error.

Syntax: define-predicate opname?
Defines a predicate opname?, usually used for determining the type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with operations. Invoking (name object arg ... executes the body of the object with self bound to object and with argument(s) arg....

Syntax: object-with-ancestors ((ancestor1 init1) ...) operation ...
A let-like form of object for multiple inheritance. It returns an object inheriting the behaviour of ancestor1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list.

Syntax: operate-as component operation self arg ...
Used in an operation definition (of self) to invoke the operation in an ancestor component but maintain the object's identity. Also known as "send-to-super".

Procedure: print obj port
A default print operation is provided which is just (format port obj) (see section Format (version 3.0)) for non-instances and prints obj preceded by `#<INSTANCE>' for instances.

Function: size obj
The default method returns the number of elements in obj if it is a vector, string or list, 2 for a pair, 1 for a character and by default id an error otherwise. Objects such as collections (see section Collections) may override the default in an obvious way.

Setters

Setters implement generalized locations for objects associated with some sort of mutable state. A getter operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named -- the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (see section Yasos). Several setters are predefined, corresponding to getters car, cdr, string-ref and vector-ref e.g., (setter car) is equivalent to set-car!.

This implementation of setters is similar to that in Dylan(TM) (Dylan: An object-oriented dynamic language, Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through setf.

Function: setter getter
Returns the setter for the procedure getter. E.g., since string-ref is the getter corresponding to a setter which is actually string-set!:
(define foo "foo")
((setter string-ref) foo 0 #\F) ; set element 0 of foo
foo => "Foo"

Syntax: set place new-value
If place is a variable name, set is equivalent to set!. Otherwise, place must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of set is usually unspecified unless used with a setter whose definition guarantees to return a useful value.
(set (string-ref foo 2) #\O)  ; generalized location with getter
foo => "FoO"
(set foo "foo")               ; like set!
foo => "foo"

Procedure: add-setter getter setter
Add procedures getter and setter to the (inaccessible) list of valid setter/getter pairs. setter implements the store operation corresponding to the getter access operation for the relevant state. The return value is unspecified.

Procedure: remove-setter-for getter
Removes the setter corresponding to the specified getter from the list of valid setters. The return value is unspecified.

Syntax: define-access-operation getter-name
Shorthand for a Yasos define-operation defining an operation getter-name that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.

Examples

;;; These definitions for PRINT and SIZE are
;;; already supplied by
(require 'yasos)

(define-operation (print obj port)
  (format port
          (if (instance? obj) "#<instance>" "~s")
          obj))

(define-operation (size obj)
  (cond
   ((vector? obj) (vector-length obj))
   ((list?   obj) (length obj))
   ((pair?   obj) 2)
   ((string? obj) (string-length obj))
   ((char?   obj) 1)
   (else
    (error "Operation not supported: size" obj))))

(define-predicate cell?)
(define-operation (fetch obj))
(define-operation (store! obj newValue))

(define (make-cell value)
  (object
   ((cell? self) #t)
   ((fetch self) value)
   ((store! self newValue)
    (set! value newValue)
    newValue)
   ((size self) 1)
   ((print self port)
    (format port "#<Cell: ~s>" (fetch self)))))

(define-operation (discard obj value)
  (format #t "Discarding ~s~%" value))

(define (make-filtered-cell value filter)
  (object-with-ancestors
   ((cell (make-cell value)))
   ((store! self newValue)
   (if (filter newValue)
       (store! cell newValue)
       (discard self newValue)))))

(define-predicate array?)
(define-operation (array-ref array index))
(define-operation (array-set! array index value))

(define (make-array num-slots)
  (let ((anArray (make-vector num-slots)))
    (object
     ((array? self) #t)
     ((size self) num-slots)
     ((array-ref self index)
      (vector-ref  anArray index))
     ((array-set! self index newValue)
      (vector-set! anArray index newValue))
     ((print self port)
      (format port "#<Array ~s>" (size self))))))

(define-operation (position obj))
(define-operation (discarded-value obj))

(define (make-cell-with-history value filter size)
  (let ((pos 0) (most-recent-discard #f))
    (object-with-ancestors
     ((cell (make-filtered-call value filter))
      (sequence (make-array size)))
     ((array? self) #f)
     ((position self) pos)
     ((store! self newValue)
      (operate-as cell store! self newValue)
      (array-set! self pos newValue)
      (set! pos (+ pos 1)))
     ((discard self value)
      (set! most-recent-discard value))
     ((discarded-value self) most-recent-discard)
     ((print self port)
      (format port "#<Cell-with-history ~s>"
              (fetch self))))))

(define-access-operation fetch)
(add-setter fetch store!)
(define foo (make-cell 1))
(print foo #f)
=> "#<Cell: 1>"
(set (fetch foo) 2)
=>
(print foo #f)
=> "#<Cell: 2>"
(fetch foo)
=> 2

Textual Conversion Packages

Precedence Parsing

(require 'pmacros an type of an object, such that (opname? object) returns #t if object has an operation opname? and #f otherwise.

Syntax: object ((name self arg ...) body) ...
Returns an object (an instance of the object system) with oper