[Prev][Next][Index][Thread]

Re: Dylan, MOP, object/relational mapping...



In Dylan you can't create bindings at runtime, so, in the very least you 
must create a bunch of variables for your accessors up front.  If you don't 
create these bindings up front, then calls to accessors corresponding to 
these bindings would give rise to undefined binding errors when 
compiled.  It would be pretty easy to write a program that read some 
database schema information and produced these initial variables.  But at 
this point you might as well just define the generics instead of 
variables.  From there on in, you can do it all dynamically, meaning, you 
could dynamically add methods to these generics based on the current 
configuration.

As far as introspection goes, nothing beyond the introspection that is 
specified in the DRM has be standardized on although both Gwydion and 
Functional Developer provide an introspection module (albeit undocumented 
in FD's case).  For instance, Functional Developer provides a methods for 
finding all the slots of a given class and then finding their accessors 
etc.  I can provide more detail if you're interested.

If you're really looking for the sort of dynamism that you've described 
then I think using a single getter and setter for the database accessors 
might be your best bet:

   define open generic attribute-value
      (entity :: <base-entity>, attribute :: <symbol>) => (value);
   define open generic attribute-value-setter
      (value, entity :: <base-entity>, attribute :: <symbol>);

then you define default methods on <base-entity> that perform lookups in 
the database as you described.  then you could write a class-definer macro 
that allowed you to override these default accessors whenever you wrote a 
subclass.  it would basically expand into the usual class definition plus 
delegator methods that specialize on singleton symbols as their attribute 
parameters and that would translate attribute-value into a call to the 
actual instance accessor:

   define method attribute-value
       (entity :: <widget>, attribute == #"height") => (value)
     widget-height(entity)
   end method;

this would then override the default attribute-value method.  i think this 
is similar to what neel was suggesting.

the disadvantage with this approach is that you need to use a mechanism 
outside the usual accessor mechanism to access slots.  with a little 
macrology you can make this a bit more palatable:

   define macro entity
     { ENTITY(?:name) }
       => { rcurry(attribute-value, ?#"name") }
   end macro;

which would then allow you to access entity slots using the following syntax:

   ENTITY(height)(x)

which might be a bit smoother than

   attribute-value(x, #"height")

what you really need is something like a reader macro which would allow a 
distinctive and succinct format for expressing our new dynamic 
accessors.  actually we had thought about such a read macro facility at 
harlequin and i will reveal that in my next message...

Jonathan Bachrach
President, Functional Objects, Inc.