Re: Multiple Inheritance eq Interfaces [was: Re: Object spec]

2003-03-06 Thread Andy Wardley
Sam Vilain wrote:
> No.  All I'm saying is that this sort of construct:
> 
>*{$_} = \&{"Class::$_"} foreach (qw(method method2 method3));

Like mixins?  Perhaps something like this:

  class My::Class;
  mixin My::Random::Number::Generator qw( rand );
  mixin My::Serialisation::Marshall qw( freeze thaw );

  # ...class def...

A



Re: Multiple Inheritance eq Interfaces [was: Re: Object spec]

2003-03-06 Thread Simon Cozens
[EMAIL PROTECTED] (Andy Wardley) writes:
> Like mixins?  Perhaps something like this:
> 
>   class My::Class;
>   mixin My::Random::Number::Generator qw( rand );
>   mixin My::Serialisation::Marshall qw( freeze thaw );

Yey! With this, the Perl6-o-meter now stands at:

PERL 5  RUBY

===[   ]
===[   ]

-- 
You're all sick, except Simon. And he's sick, too. -- Kake Lemon Pugh


Re: Object spec

2003-03-06 Thread Dave Whipp
Sam Vilain wrote:
Associations *are* fundamental object things.  Presenting them in terms of 
attributes is the real hack.
I agree with this statement; and Brent previously asked what 
associations *are*. The problem with describing them in terms of 
attributes/properties not not so much that its a hack, but that its an 
implementation. I'd like to attept to define what associations are, and 
then work out if attrubutes are the most appropriate representation 
within Perl6.

An association is a mechanism that permits one object to navgigate to 
another. If the association is bidirectional, then it is possible to 
also navigate from the target back to the source. Each direction of 
navigation should be given a unique identifer.

An association has an associated multiplicity. This is usually defined 
as either "one" or "many", with zero either permitted or excluded.

When the multiplicity is "many", then the order of navigation becomes an 
issue. This would typically be either "orderd" or "unordered"; in 
addition, we may wish to ensure uniqueness. Ordering my be either the 
order in which targets were added; arbitrary, or sorted.

An association may be thought of as a list/set/bag of pairs. Each pair 
is an instance of the relationship. If the pair is, itself, and object: 
then it can have additional attributes/methods that characterize the 
instance of the association. An example might be to record a timestamp 
of then the association was made.

An association is either "consitant", or "inconsitant". A consitant 
association is one where the number of associated targets is consistant 
with the multiplicity defined for the association. While 
building/modifying assemplies of objects, it is often necessary/useful 
to have an inconsitant association (e.g. a 1:1 association will be 
inconsitant for a short period, if one object is created before the 
other). If an inconsitant association is navigated, then results may be 
garbage. Such navigation could trigger an exception; or, in a threaded 
environment, block until the association is consitant.

It is possible to define associations that do not require objects to be 
linked/unlinked. Such associations must be "formalized". Formalization 
defines the association in terms of values of attributes. The 
association then becomes as equivalence relation. For example, if a 
"Teacher" object has a name; and a "pupil" object has a "teacher's name" 
attribute, then the association can be formalised as "$teacher.name == 
$pupil.teacher_name". The the attribute is a actually a method, then 
these relationships can become very dynamic. Relational databases 
usually use formalized associations: "$obj1.id == $obj2.foreign_key".

I've probably missed some important properties, but this should be 
enough for discussion. Whilst it is obvious that associations can be 
implemented using attributes, it seems to me that, to do so, is a bit 
like implemented a "while" loop using "if" and "goto". The opposite 
extreme: implementing attributes as associations, is also inappropriate. 
My thinking is that associations should be defined in much the same was 
as classes:

class Assoc1
  is association(
Type1 $source,
Type2 @target is sorted { $^a cmp $^b } is unique
  )
{
  ...
}
#later
  my @type2_objs = $type1_obj.target;
(Or perhaps the Perl5 arrow syntax would be more appropriate here).



Dave.



Re: Multiple Inheritance eq Interfaces [was: Re: Object spec]

2003-03-06 Thread Larry Wall
On Thu, Mar 06, 2003 at 10:16:40AM +, Simon Cozens wrote:
: > Like mixins?  Perhaps something like this:
: > 
: >   class My::Class;
: >   mixin My::Random::Number::Generator qw( rand );
: >   mixin My::Serialisation::Marshall qw( freeze thaw );
: 
: Yey! With this, the Perl6-o-meter now stands at:
: 
: PERL 5  RUBY
: 
: ===[   ]
: ===[   ]

But that's true no matter which language you put on the right.  :-)

Larry


Re: Associations between classes [was: Re: Object spec]

2003-03-06 Thread Sam Vilain
On Thu, 06 Mar 2003 05:51, Austin Hastings wrote:
> You'd like to declare the relationship between them, but this can be
> really difficult (consider e.g., nethack, in which the things you can
> "own" are constrained by weight/volume/knapsack).
> So certainly you need to be able to add code to the equation.
> Person::possess(o is Object)
> {
>   if (weight_of_my_stuff() + weight_of(o) > $self.weight_limit)
>   {
> whine(...);
>   }
>   else
>   {
> $self.stuff.push(o);
>   }
> }

No, that's not a part of the association.  That's like asking `push' to do 
that checking for you.

With the current pre-release version of Class::Tangram you could do that by 
overriding, Person->set_stuff, which would be called by 
Person->stuff_insert with the new contents of the container as an 
argument.  It is the job of the set_stuff method to check for the 
differences and do relevant modifications to the internal state of the 
object, or to raise exceptions if the new container contents are not up to 
scratch.

This may seem inefficient, but I consider it a starting point of the 
implementation (like the original version of Class::Tangram, which was 
implemented with AUTOLOAD and regexp, and took about 20 lines of code 
;-)).  It seemed cleaner than requiring classes to overload all of 
Person->stuff_insert(), Person->stuff_replace, Person->stuff_clear(), etc.

> In other cases, you don't care so much. So then it would be nice if you
> could declare the relationship and have the accessor functions get
> generated for you.

Well, use Class::Tangram then :-).

> I work with a tool that provides just a little built in support for
> this kind of thing:
> When you create a relationship (using the "relate" command) between to
> objects, you can do:
> ccm relate -from $object_spec_1
>-name $relationship_name
>-to $object_spec_2
>
> ccm unrelate [spec, as above]
>
> ccm relate -show [partial or complete spec, as above: -f -t -n]
>
> ccm query "is__of('$object_spec')"
> ccm query "has_('$object_spec')"
>
> The relate database is pretty straightforward -- a three-column table.

Also known as a `link table'.  How many columns it has, and whether it 
shares a table with either related object (like a foreign ID column), 
depends on the multiplicity of the relationship.

> The query part is supported by "magic" -- the query syntax parser knows
> how to chop up is_XXX_of() and has_XXX() predicates to extract
> relationship names.

Tangram inserts special tied variables that have the information needed and 
`auto-vivify' by loading the collection from storage when accessed.  Very 
transparent :-).

> I think that the Association concept can be implemented as a non-core
> package. You'll declare Associations like classes, except that they'll
> mostly be auto-generated. However, if you need to insert code (as
> above) you can explicitly spell out your sub.

Certainly they could.

> What would be nice would be a convention for
> accessing/creating/querying/modifying them, so that whenever we see
> "is_AssociationName_of(...)" (or whatever) we know that this is an
> association.

This is a key point.
-- 
Sam Vilain, [EMAIL PROTECTED]

  If you think the United States has stood still, who built the
largest shopping center in the world?
RICHARD M NIXON



RE: Object spec [x-adr][x-bayes]

2003-03-06 Thread Garrett Goebel
Sam Vilain wrote:
> 
> On Thu, 06 Mar 2003 05:10, Garrett Goebel wrote:
> > Several people have mentioned a desire to see Perl6
> > and Parrot facilitate object persistence. Should
> > such issues be tackled in Parrot?
> 
> Not necessarily.  Just be friendly to object persistence 
> frameworks by exporting object relationships in a 
> sensible and consistent manner.  It is those relation-
> ships that drive the object persistence frameworks, and 
> implementations of the object structure in various
> languages.

"exporting object relationships in a sensible and consistent manner"

Sounds like something worthy of more than a passing reference. In the
context of parrot, what falls within the scope of a sensible and consistent
manner? 

 
> The exact semantics and mechanisms of object persistence
> are still quite a research topic, so it is not appropriate
> yet to select one method as the best.  However, I believe
> that the concepts of Object, Attribute, Association,
> Methods are stable.
>
> > What does parrot need to facilitate object persistence
> > and cross-language OO? Obviously the OMG's UML and
> > family of specifications deal with these issues. What
> > other practical approaches exist?
> 
> UML does not deal with persistence.  It deals with
> specifying and modelling objects.

When I said "UML and family" I was lumping in Meta-Object Facility (MOF),
Common Warehouse Metamodel (CWM), Common Object Request Broker (CORBA),
Object Constraint Language (OCL), etc. 10,000+ pages of spine tingling
object modeling, persistence, and interchange specifications... Important in
itself not just as the provider of a common vocabulary and semantics for
programming, but also a helpful sleep aid.

MOF nails down Packages, Classes, Associations, Attributes, and Operations.
Objects being instances of classes... And while the OMG specs are overkill,
there's probably some gems of relevant insight in them. Especially if it is
a goal for parrot to allow python code to invoke methods on objects coded in
perl.

Over on perl6-internals you've been talking about the need for Associations.
Is the addition of associations all that's missing from Parrot to support
"exporting object relationships in a sensible and consistent manner"?

What are the traps and pitfalls that'll need to be avoided in Parrot's
design to make object persistence not just possible but realistically
feasible? For example: serializing objects without capturing their
associations. Will the absence of associations force us to rely on
attributes and convention to serialize an object's associations? I.e., as I
thought you were implying, a messy hack that'll come back to haunt us?

--
Garrett Goebel
IS Development Specialist

ScriptPro  Direct: 913.403.5261
5828 Reeds RoadMain:   913.384.1008
Mission, KS 66202  Fax:913.384.2180
www.scriptpro.com  garrett at scriptpro dot com


Re: Object spec [x-adr][x-bayes]

2003-03-06 Thread Sam Vilain
On Fri, 07 Mar 2003 05:48, Garrett Goebel wrote:
> Over on perl6-internals you've been talking about the need for
> Associations. Is the addition of associations all that's missing from
> Parrot to support "exporting object relationships in a sensible and
> consistent manner"?

A prudent question.  I believe so.

That is, with a description of a Class, its Attributes, Associations and
Methods I can generate Perl classes, a Tangram schema to map them to a SQL
Database, and ECMAScript `classes' that have the same intrinsic structure. 
And then use a JavaScript::Dumper class I've written to dump them to be
compliant with those ECMAScript classes 8-).

I'd like to be able to do that with Classes others have written, too.

> What are the traps and pitfalls that'll need to be avoided in Parrot's
> design to make object persistence not just possible but realistically
> feasible? For example: serializing objects without capturing their
> associations. 

Here's a summary that I hope backs up my assertion that it associations
will make it sufficient.  Let's consider three different cases of
persistence:

   - Mapping to a Table structure, either via an RDBMS or an ISAM library
   - Mapping to a Hash structure, either via a Berkeley DB or a filesystem
   - Serialising a structure to a stream - either a Data::Dumper/Storable
 object or an XML document

1.  Table structures.

OO -> RDBMS/ISAM mapping in a nutshell: You generally map each Class to a
table, and each attribute to a column in the database.  You add a `type'
column - unique to each Class in the storage.  Extra attributes in
sub-classes are either put in seperate tables (``vertical'' mapping) or
extra columns (``horizontal'' mapping).  To a SQL database, vertical
mapping is equivalent to horizontal mapping once both tables are joined on
their ID column.

So, you can see that Association entities are different.  They won't get
mapped to a single column - one to many relationships are (well, possibly
two - an ID field and a `type' field, to allow for arbitrary inheritance on
the target).  Many to one relationships are mapped in the *destination*
class' table.  Many to Many relationships are mapped in a *seperate* link
table.

Any of these relationships may have the addition of a slot *key* (ie a hash
key) and/or a slot *number* (ie, an array key).  Possibly both.

So, you need to know at least this about the classes:

   - All of their allowed attributes, and enough information on each to
 practically map that to a column type.

 There's the sticky issue of the maximum length of scalars, the
 approach taken by Tangram is to default to VARCHAR(255) columns and
 force the user to specify columns which should be allowed more.  But
 that is an implementation detail.

 Practically speaking, you have:
- string fields of N octet maximum length
- integers, floats, fixed point numbers
- times & dates
- enumerated types
- sets of enumerated types (ie, bitwise mappable fields)

 I see other types as derivatives :-)

 It is up to the mapper to map these standard types to SQL column
 types.  It is up to the user of the mapper to provide mapping
 functions for their own custom, non-structural attribute types to a
 storage representation.

   - Enough information about the structure of their associations to
 generate database linking information.

 So, we're talking about:

- the source class of the association.
- the minimum/maximum destination multiplicity
- whether the association has an order, and/or key associated with
  it.
- a flag to say whether this is an aggregation or a composition

 In addition, if you want to be able to place constraints on the source
 multiplicity of the relationship (such as specifying a 1 to many
 relationship, which might be implemented with a foreign key), or to
 navigate back the other way, you need to make it a 2-way association,
 so need:

- the destination class of the association.
- the minimum/maximum source multiplicity.
- whether the reverse association has an order, and/or key
  associated with it *independant* of the one coming *to* it.

   - you also need to know all of the superclass relationships.

   - I'm considering object methods as unimportant for data storage.

2. Hash structures.

[note: I'm making this bit up as I go along, as I don't know of any mappers
that actually take this approach.  Please take with as many grains as salt
as you wish and feel free to pipe up and correct me where appropriate.]

Strict Hash databases, such as Berkerley, are a slightly different beast. 
You'd generally map chunks of your data structure to a single hash entity. 
A filesystem directory could also be considered a variant of a hash.

A straightforward approach would be to map from the store's `object ID' to
a serialisation of just that object.  I will c