accessing contents of compound data objects
Matthias Radestock <[email protected]>
| Newsgroups | gmane.comp.java.sisc.devel |
|---|---|
| Organization | LShift Ltd |
| Message-ID | <[email protected]> |
SISC currently employs an interesting paradigm for accessing the contents of some compound data objects. We share this paradigm with Paul Graham's Arc. Paul describes it as follows: <quote> Any compound data object (meaning one with several separately addressable parts) behaves like a function on indices. So for example to get the third element of a list you "call" the list with 2 as an argument. This makes programs shorter and saves us having separate access functions for each data type. You can literally use compound data objects anywhere you could use a function, including as the first argument to map (like Common Lisp's mapcar, but works on any sequence). </quote> In SISC this applies to hash tables, Java objects and Scheme objects. Here are some examples ;return contents of entry for key 'bar in hashtable foo-ht (foo-ht 'bar) ;set contents of entry for key 'foo in hashtable foo-ht to 'baz (foo-ht 'bar 'baz) ;return contents of slot 'bar of (Java) object foo-obj (foo-obj 'bar) ;set contents of slot 'bar of (Java) object foo-obj to 'baz (foo-obj 'bar 'baz) ;return contents of slot 'bar3 of the contents of slot 'bar2 of ;the contents of slot 'bar1 of (Java) object foo-obj (foo-obj '(bar1 bar2 bar3)) ;set contents of slot 'bar3 of the contents of slot 'bar2 of ;the contents of slot 'bar1 of (Java) object foo-obj to 'baz (foo-obj '(bar1 bar2 bar3) 'baz) The advantages of this approach are clear and explained well by Paul above. However, when employed in a Scheme system the approach also has disadvantages: * R5RS requires |procedure?| to return #f for any object that can appear in the operator position of an application. This means that any datatypes employing the above paradigm will be treated as procedures. This is not really a semantic problem, but one of terminology that runs counter to established practice. * R5RS requires disjointness of the core data types. In combination with the previous point this means that none of the core compound data types, i.e. lists, vectors, and strings, can use the paradigm. This results in inconsistency. * The conflation of the syntax for procedure application with that of field access makes code hard to read. * By convention, any mutating operation carries a "!" suffix. The paradigm breaks this convention. Generally, the paradigm does not feel very idiomatic in Scheme. The alternative is to provide accessor and modifier functions for all data types. We already have these in SISC for hashtables. Scott's forthcoming collection srfi is going to define naming schemes for operations on future collection types and will also specify polymorphic procedures that can operate on several collection types. For SISC's object system we could follow what MIT's SOS does - much of SISC's object system API is based on SOS, so this would be a very natural change: * When defining a class, the slot descriptor can contain a reference to an accessor generic procedure and modifier generic procedure. Methods are automatically added to these. As a result, accessing the slot 'foo of any object (including Java objects) could be done with a call to |get-foo| and |set-foo!|. * (|slot-accessor-method| <class> <slot-name>) and (|slot-modifier-method| <class> <slot-name>) return accessor/modifier methods for a specific slot of instances of a specific class. * (|slot-accessor| <class> <slot-name> and (|slot-modifier| <class> <slot-name>) return procedures for accessing/setting a slot of instances of a specific class. * (|slot-value| <instance> <slot-name>) and (|slot-value! <instance> <slot-name> <value>) provide direct access to an object's slots. Note that the accessor/modifier functions can be implemented very efficiently if the object layout permits it. For instance, they directly correspond to java.lang.reflect.Field.get()/set(). Also, note that we can use function composition to accomplish chained field access, e.g. (foo-obj '(bar1 bar2 bar3)) becomes ((compose get-bar3 get-bar2 get-bar1) foo-obj) which is more verbose but also far more readable. [writing a chained modifier is a bit tricker but with a little helper function becomes equally concise]. So, as you may have guessed by now, I'm considering abonding the special field access paradigm in favour of accessor/modifier functions. Comments / suggestions / objections? Matthias. ------------------------------------------------------- This SF.net email is sponsored by: ValueWeb: Dedicated Hosting for just $79/mo with 500 GB of bandwidth! No other company gives more support or power for your dedicated server http://click.atdmt.com/AFF/go/sdnxxaff00300020aff/direct/01/