December 01, 2001
Russ Lewis wrote:
> 
> a wrote:
> 
> >         If the test to see if they are not at all related isn't any more
> > complicated than test for specific relation ships (i.e.. parent of,
> > child of, same) then I'd hate to burden the operation with an exception
> > throw.  Are we sure that there will never be a case where someone would
> > reasonably want to test if two objects are not related?
> 
> It's thinking about this that caused me to ponder the greatestCommonClass idea described in my subsequent post.  The test to see if two objects are related could be:
> 
> if( greatestCommonClass(ptr1,ptr2) != Object)

	A nifty idea, but it seems more appropriate in a dynamically typed
language like perl or python.  That still doesn't tell you that ptr1 is
not ptr2's parent or visa versa.  I was thinking that

	ptr1 <> ptr2;

might mean true if neither of them is the descendant of the other.
Frankly, I don't care if their closest common ancestor is Object or
something closer.  The greatest common class really doesn't provide
that.  You could implement <> with it, but you could also just use the
<= & >= operators just as well.
	I'm trying to figure out how some one might reasonable use the function
you describe, but I know the operators I've suggested would not be
enough to implement it in any optimal fashion.
	Will/should D allow a programmer to use rtti to determine what type of
object to allocate at runtime?  If so, it feels like it could seriously
compromise the abilities of compile time type checking severely.  It
could just be the cost of play with the operation.  I suspect it could
be very useful with regard to generic programming depending on how that
is implemented.

Dan
December 01, 2001
a wrote:

> Russ Lewis wrote:
> >
> > a wrote:
> >
> > >         If the test to see if they are not at all related isn't any more
> > > complicated than test for specific relation ships (i.e.. parent of,
> > > child of, same) then I'd hate to burden the operation with an exception
> > > throw.  Are we sure that there will never be a case where someone would
> > > reasonably want to test if two objects are not related?
> >
> > It's thinking about this that caused me to ponder the greatestCommonClass idea described in my subsequent post.  The test to see if two objects are related could be:
> >
> > if( greatestCommonClass(ptr1,ptr2) != Object)
>
>         A nifty idea, but it seems more appropriate in a dynamically typed
> language like perl or python.  That still doesn't tell you that ptr1 is
> not ptr2's parent or visa versa.

Sure it does!

switch( greatestCommonClass(ptr1,ptr2) )
{
case ptr1.class:
   // ptr1 is a parent of ptr2

case ptr2.class:
    // ptr2 is a parent of ptr1

case Object:
    // no commonality

default:
     // they share a common base class
};

> I was thinking that
>
>         ptr1 <> ptr2;
>
> might mean true if neither of them is the descendant of the other.
> Frankly, I don't care if their closest common ancestor is Object or
> something closer.  The greatest common class really doesn't provide
> that.  You could implement <> with it, but you could also just use the
> <= & >= operators just as well.
>         I'm trying to figure out how some one might reasonable use the function
> you describe, but I know the operators I've suggested would not be
> enough to implement it in any optimal fashion.
>         Will/should D allow a programmer to use rtti to determine what type of
> object to allocate at runtime?  If so, it feels like it could seriously
> compromise the abilities of compile time type checking severely.  It
> could just be the cost of play with the operation.  I suspect it could
> be very useful with regard to generic programming depending on how that
> is implemented.

I don't know the details of RTTI (I don't know *a lot* of the detail of compilers, but wouldn't the vtable pointer be a good RTTI identifier?  Two objects of the same class would have identical vtable pointers.  If you wanted, at runtime, the class name, then the vtable could include a pointer to a class name field.  Even if the class doesn't need a vtable, you could include a vtable pointer and use it to gain access to the class name and do RTTI.

As for the usefulness of greatestCommonClass (I'd love to call it gcc...if the acronym wasn't taken...what about 'gcp' for 'greatestCommonParent'?), I offered a very simple snippet from a generic container class in the original post.  Would it be useful for me to flesh this example out?

--
The Villagers are Online! http://villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]


December 01, 2001
Russ Lewis wrote:
> 
> a wrote:
> 
> > Russ Lewis wrote:
> > >
> > > a wrote:
> > >
> > > >         If the test to see if they are not at all related isn't any more
> > > > complicated than test for specific relation ships (i.e.. parent of,
> > > > child of, same) then I'd hate to burden the operation with an exception
> > > > throw.  Are we sure that there will never be a case where someone would
> > > > reasonably want to test if two objects are not related?
> > >
> > > It's thinking about this that caused me to ponder the greatestCommonClass idea described in my subsequent post.  The test to see if two objects are related could be:
> > >
> > > if( greatestCommonClass(ptr1,ptr2) != Object)
> >
> >         A nifty idea, but it seems more appropriate in a dynamically typed
> > language like perl or python.  That still doesn't tell you that ptr1 is
> > not ptr2's parent or visa versa.
> 
> Sure it does!
> 
> switch( greatestCommonClass(ptr1,ptr2) )
> {
> case ptr1.class:
>    // ptr1 is a parent of ptr2
> 
> case ptr2.class:
>     // ptr2 is a parent of ptr1
> 
> case Object:
>     // no commonality
> 
> default:
>      // they share a common base class
> };

	I hadn't thought of that.  I don't know if switch was intended to work
with anything other than integral types and maybe strings.  It might be
nice if it did, but depending on how switch is done, there might be
other nasty side effects.  Also, I thought the case values had to be
constants know at compile time.

> > I was thinking that
> >
> >         ptr1 <> ptr2;
> >
> > might mean true if neither of them is the descendant of the other.
> > Frankly, I don't care if their closest common ancestor is Object or
> > something closer.  The greatest common class really doesn't provide
> > that.  You could implement <> with it, but you could also just use the
> > <= & >= operators just as well.
> >         I'm trying to figure out how some one might reasonable use the function
> > you describe, but I know the operators I've suggested would not be
> > enough to implement it in any optimal fashion.
> >         Will/should D allow a programmer to use rtti to determine what type of
> > object to allocate at runtime?  If so, it feels like it could seriously
> > compromise the abilities of compile time type checking severely.  It
> > could just be the cost of play with the operation.  I suspect it could
> > be very useful with regard to generic programming depending on how that
> > is implemented.
> 
> I don't know the details of RTTI (I don't know *a lot* of the detail of compilers, but wouldn't the vtable pointer be a good RTTI identifier?  Two objects of the same class would have identical vtable pointers.  If you wanted, at runtime, the class name, then the vtable could include a pointer to a class name field.  Even if the class doesn't need a vtable, you could include a vtable pointer and use it to gain access to the class name and do RTTI.
> 
> As for the usefulness of greatestCommonClass (I'd love to call it gcc...if the acronym wasn't taken...what about 'gcp' for 'greatestCommonParent'?), I offered a very simple snippet from a generic container class in the original post.  Would it be useful for me to flesh this example out?

	I'm not concerned with how rtti will be implemented.  I was thinking
that the best use I could find for such a function would be to get type
information at runtime in order to allocate a new object of this
dynamically determined type.

	base* ptr = greatestCommonClass(ptr2,ptr3).new(swizzle(ptr2,ptr3));

Ya, I know the syntax is broken, but hopeful the idea was clear.  In any
case.  I find the above dangerous.  It's not as bad as creating a type
at runtime in perl, but it feel like it is in the same arena.  Of
course, dangerous does not mean useless.  I just like to understand when
I have enough rope to hang myself.
	I guess greatestCommonClass would also be useful for determining if two
classes have a common ancestor other that Object.  That's about the only
uses I see for it.  You could it to see if two classes have a common
ancestor that is a descendent of some known base like so:

	if(greatestCommonClass(p1, p2) >= WigetBase.class)
		meaningfulThings();

but you would get the same results with:

	if(p1.class >= WigetBase.class && p2.class >= WidetBase.class)
		meaningfulThings();

I'm not saying there aren't more uses.  I'm just too dense to see them.

Dan
December 01, 2001
How about this class hierarchy:

interface Comparable;
class Apples : Comparable;
class ApplesChild1 : Apples;
class ApplesChild2 : Apples;
class Oranges : Comparable;
class OrangesChild1 : Oranges;
class OrangesChild2 : Oranges;

The idea here is that both Apples and Oranges implement the functions of interface Comparable. Obviously, you can't compare apples and oranges. :)

So here's a snippet from a container class:

int Compare(Object *ptr1, Object *ptr2)
{
    Class common = gcp(ptr1,ptr2); // greatestCommonParent

    if(common = Object)
        throw Exception("Cannot compare objects: no common parent classes");
    if( !common.implements(Comparable) )
        throw Exception("Cannot compare objects: common parent class does not implement interface
Comparable");
    return ptr1->Compare(ptr2);
}



Does this code make sense to anybody but me?

--
The Villagers are Online! http://villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]


December 01, 2001
a wrote:

> I hadn't thought of that.  I don't know if switch was intended to work with anything other than integral types and maybe strings.  It might be nice if it did, but depending on how switch is done, there might be other nasty side effects.  Also, I thought the case values had to be constants know at compile time.

heh.  Well, it can be an if...else if otherwise.  Would be cool if switch would work on this, though...

--
The Villagers are Online! http://villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]


December 02, 2001
Russ Lewis wrote:
> 
> How about this class hierarchy:
> 
> interface Comparable;
> class Apples : Comparable;
> class ApplesChild1 : Apples;
> class ApplesChild2 : Apples;
> class Oranges : Comparable;
> class OrangesChild1 : Oranges;
> class OrangesChild2 : Oranges;
> 
> The idea here is that both Apples and Oranges implement the functions of interface Comparable. Obviously, you can't compare apples and oranges. :)
> 
> So here's a snippet from a container class:
> 
> int Compare(Object *ptr1, Object *ptr2)
> {
>     Class common = gcp(ptr1,ptr2); // greatestCommonParent
> 
>     if(common = Object)
>         throw Exception("Cannot compare objects: no common parent classes");
>     if( !common.implements(Comparable) )
>         throw Exception("Cannot compare objects: common parent class does not implement interface
> Comparable");
>     return ptr1->Compare(ptr2);
> }
> 
> Does this code make sense to anybody but me?

I see how it works, but it is not very general purpose.  If Apple and
Orange had some other common base (say fruit) this suddenly breaks.
This container simply uses the first ancestor after Object to divide
types into equivalence classes.  A general container should not make
this type of assumption.  A domain specific probably ought to deal more
with the base classes it was designed for.
	I guess you could have a common base other than object (again Fruit)
and make it a design decision that direct children of that class are not
comparable.  I would also put the requirement to implement compare in
that class.  I guess I see how it can be used.  I don't like it, but it
will take a while for me to decide if it's just because it's new to me.
	You do know that such a design will require the eventual addition of
multiple inheritance once the biological engineers make a fruit that can
be compared to it's own kind as well as apples and oranges.  :-)
	Also your error message in the first if is wrong.  All classes in D
have a common parent class.  I see you are trying to simulate a C++
style object model in this sense but it may clash with D code that does
not differentiate between Objects that only have a parent of Object.

Dan
December 02, 2001
> Will/should D allow a programmer to use rtti to determine what type of object to allocate at runtime?  If so, it feels like it could seriously compromise the abilities of compile time type checking severely.  It could just be the cost of play with the operation.  I suspect it could be very useful with regard to generic programming depending on how that is implemented.

The ability to store an object's type to a file and then once you reload that type use some kind of virtual constructor scheme to use the loaded type to construct a new object.  Probably would want to pass the file as a constructor parameter.  If you can support this, it will make storing out object hierarchies much easier.  I suppose we could make our own Streamable class which provides this functionality so long as we can get a storable value from the RTTI system from an object to represent its type, and make 'new' able to understand such values.  It'd probably end up returning an Object reference since the compiler couldn't know what exact type it would be.  One could always then inquire the object's type if we needed to work with it, or we could just typecast it to a known base class type.  (similar to malloc)

Sean


December 02, 2001
Walter says D's switch statement allows strings.  I don't see why it has to be limited to only constants, since a switch can always be rewritten as a series of if .. else if ... else clauses (with a break for a case being simulated with a goto) and if's are not limited to only constants.

Sean

"Russ Lewis" <spamhole-2001-07-16@deming-os.org> wrote in message news:3C08E67F.664DE454@deming-os.org...
> a wrote:
>
> > I hadn't thought of that.  I don't know if switch was intended to work with anything other than integral types and maybe strings.  It might be nice if it did, but depending on how switch is done, there might be other nasty side effects.  Also, I thought the case values had to be constants know at compile time.
>
> heh.  Well, it can be an if...else if otherwise.  Would be cool if switch
would work on this,
> though...



December 02, 2001
Speaking of virtual constructors (which are probably
the most important point in this scheme), Walter
said that it could be a "good idea". Hopefully this
means that we'll see them in D.


December 03, 2001
"Sean L. Palmer" wrote:
> 
> Walter says D's switch statement allows strings.  I don't see why it has to be limited to only constants, since a switch can always be rewritten as a series of if .. else if ... else clauses (with a break for a case being simulated with a goto) and if's are not limited to only constants.
> 
> Sean
> 
> "Russ Lewis" <spamhole-2001-07-16@deming-os.org> wrote in message news:3C08E67F.664DE454@deming-os.org...
> > a wrote:
> >
> > > I hadn't thought of that.  I don't know if switch was intended to work with anything other than integral types and maybe strings.  It might be nice if it did, but depending on how switch is done, there might be other nasty side effects.  Also, I thought the case values had to be constants know at compile time.
> >
> > heh.  Well, it can be an if...else if otherwise.  Would be cool if switch
> would work on this,
> > though...


	I believe if was suppose to be the high level equivalent of a
conditional branch.  Switch was supposed to be the equivalent of a jump
table.  The is a performance difference.  C made it pretty easy to look
at the code and know what the compiler was going to do to it.

Dan