dotgnu-visionaries
[Top][All Lists]
Advanced

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

Re: [Visionaries] DG-Scheme


From: Peter Minten
Subject: Re: [Visionaries] DG-Scheme
Date: Mon, 28 Apr 2003 12:57:03 +0200

Peter Minten wrote:
> 
> Peter Minten wrote:
> >
> > Peter Minten wrote:
> > >
> > > Hi folks,
> > >
> > > I did a little thought experiment today, making Scheme truly OO and AO 
> > > (Aspect
> > > Oriented), it turned out that's not so hard, if you add the idea of 
> > > metadata. A
> > > language that is flexible, OO, AO and has metadata would be the ideal 
> > > language
> > > for many webservices. I believe DG-Scheme (as I call it) meets those
> > > qualifications. What follows is an explanation about the specifics of 
> > > DG-Scheme
> > > (well, as far as I've managed to map them out in a couple of hours).
> >
> > Additions.
> 
> Addendum.

Yet Another Addendum

Some metadata is related to the value of a field and some is related to the
field itself. An example of the former is type, an example of the latter is the
description of the field. I previously tried to solve this by binding (not
Scheme binding) metadata to the memory location and normal data to the value.
The examples wouldn't work if it's done that way however. That's why I'm now
introducing a way to get the reference of a field instead of the field itself. 

Objects of the Reference class (Reference objects or refs) are used to store the
references. The way to get the reference of object foo is ^foo. The way to get
the reference of field foo of class bar is bar.^foo . If references occur in a
chain (foo.bar.baz) the Reference objects should not be used (because of
efficiency), how the interpreter should do it is unspecified. A little
terminology, the data bound to the reference of a field is called the r-data of
the field, the data bound to the value of a field is called the v-value of the
field.

A new development, made possible by the new reference model, is that triggers
are no longer metadata. I don't like it when something is metadata that does not
tell you something about the target object. Triggers are now implemented using
so called Trigger objects. A Trigger object is simply a very stripped down
version of a one dimensional array which stores procedure objects. When the
trigger is fired using (Trigger.fire . args) the procedures get executed. Note
that it's possible for outside data to fire a trigger, restriction metadata can
be used to prevent this.

Triggers are defined like this: (Trigger.new __lambda-list__) where
__lambda-list__ is a lambda list. I've removed the Aspect Oriented triggers,
they create a too big performance strain for too little value and AO stuff can
be applied during a separate compilation (compilation here mainly means macro
expansion) fase.

Procedures are implemented as objects of class Procedure. Procedures are defined
using lambda or Procedure.new, the two are equivalent. So the syntax of
Procedure.new is (Procedure.new formals body) if the definition of lambda is
(lambda formals body). Procedures don't have a fire or activate method, they are
executed when evaluated.

Every object now has a meta field which contains the metadata as a hash, there
is also a ^obj.meta field for every obj (thus metadata can be bound both to the
reference and the value).

It's possible to create fields by copying fields from another
class/module/object. This is done using the include family of procedures. The
most basic variant (include fieldname) simply copies a field from another
class/module/object _and evaluates it's initial value in the current context_.
The variant (include-as fieldname newname) does the same as (include) but
renames the field to avoid name conflicts.

The last variant is the most useful, it is used to mix in a whole bunch of
fields at once. The fields have to be in a module (well, everything is
automatically in a module) and marked with the [mixin] attribute. When I say
(include-mixin modulename) all the mixin fields in that module (the module is
known in this context as the mixin) are included.

A good example of the use of mixins is this (in reality the definition will be
more complex and extended, but this is the basic idea):
(define-module Comparable
  (define (< a . b)
    (= (<=> a b) -1)
    [mixin])

  (define (<= a . b)
    (or (= (<=> a b) -1)
        (= (<=> a b) 0))
    [mixin]))

(define-class Foo
  (include-mixin Comparable)
  (define (<=> a b)
    (if (a.bar b)
        -1
        (if (a.baz b)
            0
            1))))

Class Foo only has to define the spaceship operator to get the < and <=
operators for free.

Note that mixins replace multiple inheritance and interfaces in DG-Scheme.

Once again I've messed up the definition of Generic. Generic isn't an object
(well, it isn't directly an object) but a class. For every field with multiple
definitions there is one Generic object. A short example:
(define-class Foo
  (define-generic (bar a b) #f)
  (define-generic (bar a (b Foo)) #t))

At the first define-generic of bar a Generic object would have been placed in
the Bar field and the (bar a b) definition would have been added to it. The
second define-generic of bar would simply add a new definition to the Generic.

Metadata is Object Oriented. There is one class Metadata and all metadata
derives from that class. Thus the Description metadata class would be a subclass
of Metadata. The metadata declaration [Description "foo"] would NOT create a new
Description object and place it's value in the Description metadata field.
Instead the (Description.add object value) method would be called, which places
the metadata into the metadata hash. Note that this works a little different for
Reference objects of course.

All metadata classes should be placed in submodules named Metadata.
Implementations are required to look first into Metadata modules for metadata
classes and then in other modules. This is to prevent metadata from poluting the
normal namespaces (modules).

With most important low level issues resolved it's time to begin planning the
baselib. The baselib will have clear documentation written in RDF. I chose RDF
because the baselib is best represented as a web, and well I like RDF :-). The
documentation outputter will be written in DG-Scheme and will use the classes in
the RDF module.

Here is a rough structure of the baselib:

Base -- Top level, contains basic data types like Number, String and Hash.
|
+- IO -- Basic I/O classes
|  |
|  +- Net -- Network I/O classes (equivalent of System.Net in C#)
|
+- Math -- Math classes
|
+- Metadata -- A whole bunch of standard metadata
|
+- Web -- Web stuff
   |
   +- HTML -- HTML creation/parsing stuff
   |
   +- Protocols -- Web protocols
   |  |
   |  +- Jabber
   |  |
   |  +- XML-RPC
   |  |
   |  +- Http
   |
   +- RDF -- RDF classes
   |
   +- Services -- Webservice client classes
   |  |
   |  +- Server -- Webservice server classes
   |
   +- XML -- XML classes


Greetings,

Peter



reply via email to

[Prev in Thread] Current Thread [Next in Thread]