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/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.