This email is part of a brain dump from my thoughts over the last week while I was away from a computer. If anything doesn't make sense, I will clarify or expand it in the following days.

I believe that Perl 6 already has basically all of the necessary parts built-in for implementing a true relational database, and that any needed remainder can be added and integrated in an elegant fashion, as I will outline and/or ask about.


At the center of this idea is the thought that the "Tuple" and "Relation" of the relational data are not each single classes, but rather are each roles / abstract interfaces that many classes can be composed of / implement.

This is much the same as how I see the existing "Array" and "Hash" of Perl 6, where each is a role, and eg, that "Array of Int" and "Array of Str" are 2 different actual classes (or roles) that .does(Array); in this context, saying "Array of ..." is acting as a class generator which defines a new class that composes the Array role. I say that "Array of Int" and "Array of Str" are 2 different classes because the Perl 6 type system would treat each as being a repository for different sets of possible values, and would reject the assignment of one to the other.

And so, a "Tuple" type is essentially defined using an ordinary class (or classless object type) definition that .does(Tuple) but that that it also has certain restrictions. A Tuple value is then simply an object of that class.

The routines that the Tuple class provides are essentially just wrappers over certain meta-class and/or class routines, and Tuple does not add any new attributes nor hide any existing class functionality. The attributes of the Tuple and the attributes defined by the class are one and the same.

The design restrictions that a Tuple doing class must obey, or appear to obey as far as its users can see, are such as these:

1. All significant attributes which together define the Tuple object's value must be public and/or have accessors with the same names as the attributes (extra implicit attributes that eg index those are not significant in this sense); an introspection method should also exist where one can inquire what the names and types of the significant attributes are; conceptually, a Tuple class is transparent.

2. The Tuple class must have a constructor that takes values for all significant attributes of the new object. Every logically distinct Capture of that constructor must produce a logically distinct new object.

3. A Tuple class needs to provide the interface details necessary that the Perl 6 type system can treat it as a value type. The === operator should return True just for 2 Tuple objects that are of the same class and where all pairs of corresponding significant attributes using === return True.

Conjecture: As well, 2 Tuple objects that are of different classes, where at least one is anonymous, should compare like they were of the same class if their significant attribute definition sets are identical; this is so a system where most classes are generated from other classes DWIM correctly, like two distinct "Array of Int" have the same definition.

4. Conjecture: all Tuple classes should be immutable following their construction, either actually or in appearance, but this may not be essential for all uses of it.

5. Each significant Tuple attribute is mutually exclusive from all of the others, in that the interface to an attribute conceptually maps 1:1 to the attribute; reading or changing any of them does not have visible side-effects on any others. This is similar to how array or hash elements are exclusive.

Now, a "Relation" type is one step removed; it is simply or in appearances to the user a "Set of <Tuple-doing-class>" or some-such that also .does(Relation), or perhaps alternately, a "Relation" type could be declared with "Relation of <Tuple-doing-type>", which looks more natural.

A "Relation" is a "Set" that is restricted to all of its members being of the same single class that is specified in the Relation type definition, and within that constraint, it is useable like any Set, and the Relation role adds several additional routines that wrap meta-class or class methods of the Set, but don't hide any existing features.

Presumably any Tuple used in a Relation has to be immutable, since changing a Tuple that is a member of a Relation would have the same issues to contend with as when you change a mutable object that is used as a Hash key.

Inherited from Set, a Relation class must have the necessary details that the Perl 6 type system can treat it as a value type, including that === works.

It goes without saying that any attribute of a Tuple can be either a class that .does(Tuple) or that .does(Relation), as it can be any other class.

Note that many of the methods which the Tuple and Relation roles provide will have the effect of generating new anonymous classes, along with objects of said new classes; these may very well be in fact be classless objects as is appropriate; in some cases, the new objects will have the same classes as the parent objects. Some will generate one output object from one input object and/or the invocant; others will generate one output object from 2 or N input objects.


Now, in order for all the above to work effectively, a few things may or will be needed in the Perl 6 meta-model and programmatic API to said:

1. It must be possible to define new classes or classless objects whose definition can be determined at run time or compile time depending on what data is known.

2. It must be possible to both read the list of significant attributes from an existing class definition / meta-class object, including their names and full type definitions, and to copy these names and definitions into a new class definition or classless object.

3. Generally speaking, it should be possible to take several existing meta-class objects and treat their attribute lists as sets which can then have set operations applied to them, like union, intersect, subtract, etc; anything that supports this will only succeed if same-named attributes also have identical type definitions; non-identical types for the same names result in an exception. Or additionally, it should be possible to copy one class definition into another one to use as a basis for further changes. If this isn't built-in, then the Tuple|Relation Role can implement this over #1/#2. Note that these such derived definitions are static and don't change if their derived-from class definitions later change, as they aren't subclasses.

4. We need to be able to programmatically define accessors and constructors for new classes/classless-objects too, unless those come for free when we declare attributes public-ish.


In closing for now, I imagine that a lot of this stuff is connected to the meta-model, though doing it well will have clean support in the language syntax as well.

Feedback is appreciated.

Thank you. -- Darren Duncan

Reply via email to