Re: Protocols

2003-07-24 Thread David Wheeler
On Wednesday, July 23, 2003, at 05:57  PM, chromatic wrote:

The first is a deeper question -- besides inheritance, there's 
delegation, aggregation, and reimplementation (think mock objects) 
that can make two classes have equivalent interfaces.  I'd like some 
way to mark this equivalence *without* having to inherit from an 
abstract base class and I wish that interface equivalence were checked 
before inheritance, as per Luke's idea.
Sounds like you want Java-style interfaces to me.

Regards,

David

--
David Wheeler AIM: dwTheory
[EMAIL PROTECTED]  ICQ: 15726394
http://kineticode.com/ Yahoo!: dew7e
   Jabber: [EMAIL PROTECTED]
Kineticode. Setting knowledge in motion.[sm]


Re: Protocols

2003-07-24 Thread David Wheeler
On Thursday, July 24, 2003, at 09:25  AM, Kurt Starsinic wrote:

Sounds like you want Java-style interfaces to me.
Follow the thread back.  Objective-C had them way first, and their
ur-name is protocols.
D'oh! Sorry, I had read that, but then forgot.

David

--
David Wheeler AIM: dwTheory
[EMAIL PROTECTED]  ICQ: 15726394
http://kineticode.com/ Yahoo!: dew7e
   Jabber: [EMAIL PROTECTED]
Kineticode. Setting knowledge in motion.[sm]


Re: Protocols

2003-07-24 Thread chromatic
On Thursday, July 24, 2003, at 08:49 AM, David Wheeler wrote:

On Wednesday, July 23, 2003, at 05:57  PM, chromatic wrote:

The first is a deeper question -- besides inheritance, there's 
delegation, aggregation, and reimplementation (think mock objects) 
that can make two classes have equivalent interfaces.  I'd like some 
way to mark this equivalence *without* having to inherit from an 
abstract base class and I wish that interface equivalence were 
checked before inheritance, as per Luke's idea.
Sounds like you want Java-style interfaces to me.
No, I think Java interfaces are a kluge to get around copying a broken 
type system and the lack of multiple inheritance.

I don't want to litter both the caller and the callee with interface 
declarations that do nothing but say this thing here understands the 
same methods as that thing there.  The caller, fine -- that's the 
place it belongs.

If I have to modify the callee to do this, I've insufficient 
polymorphism.

Think of it this way.  If you write Perl 5 code like this:

sub some_method
{
my $self = shift;
die Bad object unless ref $self = 'Some::Class';
# do something useful...
}
someone will have to change or override some_method() if he wants to 
subclass it.  You could make his life a little easier by writing:

sub some_method
{
my $self = shift;
die Bad object unless $self-isa( 'Some::Class' );
# do something useful...
}
I'm suggesting to go the next step and let the code say, Hey, if it 
acts like an instance of Some::Class, I don't care where it gets its 
behavior.  I'll treat it like an instance of Some::Class.  That's what 
I do with Class::ActsLike, and that's what I'd like to see here:

sub some_method
{
my $self = shift;
die Bad object unless $self-acts_like( 'Some::Class' );
# do something useful...
}
Now it doesn't care whether I've inherited, aggregated, delegated, or 
reimplemented.  My argument is that it shouldn't have to care.  It 
should only care that I've somehow promised that what I'm passing in 
behaves like it expects it to behave.  How it does that is 
uninteresting.

-- c



Re: Protocols

2003-07-24 Thread Austin Hastings

--- chromatic [EMAIL PROTECTED] wrote:
 On Thursday, July 24, 2003, at 08:49 AM, David Wheeler wrote:
 
  On Wednesday, July 23, 2003, at 05:57  PM, chromatic wrote:
 
  The first is a deeper question -- besides inheritance, there's 
  delegation, aggregation, and reimplementation (think mock objects)
 
  that can make two classes have equivalent interfaces.  I'd like
 some 
  way to mark this equivalence *without* having to inherit from an 
  abstract base class and I wish that interface equivalence were 
  checked before inheritance, as per Luke's idea.
 
  Sounds like you want Java-style interfaces to me.
 
 No, I think Java interfaces are a kluge to get around copying a
 broken type system and the lack of multiple inheritance.

Multiple Inheritance != Protocols | Interfaces

How much C++ code have you seen with unused stuff in the objects
because I had to inherit from that class to get the MI behavior I
wanted, but I no longer use those attributes.

Protocols/Interfaces is a way of saying My structure is none of your
damn business, but I comply with the rules you've set.

MI, on the other hand, can be implemented with a protocol and a has-a
relationship, albeit at a significant cost in coding dispatch methods.

There's an argument for supporting both.

class Foo is all(DessertTopping, FloorWax) {
}

 I don't want to litter both the caller and the callee with interface 
 declarations that do nothing but say this thing here understands the
 same methods as that thing there.  The caller, fine -- that's the 
 place it belongs.

I disagree, and I hope you've simply swapped terms around.

I think you want to declare I comply with ruleset X at the callee
object level. That enables the compiler to (1) check that you're not
lying; and (2) optimize based on (1).

 If I have to modify the callee to do this, I've insufficient 
 polymorphism.

At the caller side, you want to say I require something which
complies with ruleset X and have it be enforced to a user-configurable
extent.

Obviously calling a method which doesn't exist should be an error. But
(especially in large systems) it should be possible to slack off on the
call-side checking, because you know you're doing the checking on the
callee side at compile time.

 Think of it this way.  If you write Perl 5 code like this:
 
   sub some_method
   {
   my $self = shift;
   die Bad object unless ref $self = 'Some::Class';
   # do something useful...
   }
 
 someone will have to change or override some_method() if he wants to 
 subclass it.  You could make his life a little easier by writing:
 
   sub some_method
   {
   my $self = shift;
   die Bad object unless $self-isa( 'Some::Class' );
   # do something useful...
   }
 
 I'm suggesting to go the next step and let the code say, Hey, if it 
 acts like an instance of Some::Class, I don't care where it gets its 
 behavior.  I'll treat it like an instance of Some::Class.  That's
 what 
 I do with Class::ActsLike, and that's what I'd like to see here:
 
   sub some_method
   {
   my $self = shift;
   die Bad object unless $self-acts_like( 'Some::Class' );
   # do something useful...
   }
 

I notice all this is on the callee side. I'm hoping you swapped er/ee
above.

 Now it doesn't care whether I've inherited, aggregated, delegated, or
 reimplemented.  My argument is that it shouldn't have to care.  It 
 should only care that I've somehow promised that what I'm passing in 
 behaves like it expects it to behave.  How it does that is 
 uninteresting.

I agree. Luke agrees. The extent to which this is formalized is open
for discussion, but I think Damian doesn't agree (see his example some
time back about class Dog vs. class Tree). 

=Austin





Re: Protocols

2003-07-24 Thread chromatic
On Thursday, July 24, 2003, at 11:17 AM, Austin Hastings wrote:

No, I think Java interfaces are a kluge to get around copying a
broken type system and the lack of multiple inheritance.
Multiple Inheritance != Protocols | Interfaces
I quite agree, but I've done enough Java to know that if they could 
have solved it with MI, they would have.

Protocols/Interfaces is a way of saying My structure is none of your
damn business, but I comply with the rules you've set.
Yes, exactly.

I disagree, and I hope you've simply swapped terms around.

I think you want to declare I comply with ruleset X at the callee
object level. That enables the compiler to (1) check that you're not
lying; and (2) optimize based on (1).
At least one of us is using caller/callee in the X11 sense.  What I 
mean and what I think you mean is:

	method foo ( Thingie $t ) { ... }

	$object-foo( $behaves_like_thingie );

foo() says, Give me something that I can treat like a Thingie.  I 
don't care HOW it does it, I just want it to do something sane.

$behaves_like_thingie is an instance of a class that somehow says, 
Hey, I act like Thingie.  I'm substitutable for Thingie if you don't 
break my encapsulation.

If we're just confused over a bit of terminology, we're in violent 
agreement on the idea, which is much more important.

-- c



Re: Protocols

2003-07-24 Thread Austin Hastings

--- chromatic [EMAIL PROTECTED] wrote:
 On Thursday, July 24, 2003, at 11:17 AM, Austin Hastings wrote:
 
  No, I think Java interfaces are a kluge to get around copying a
  broken type system and the lack of multiple inheritance.
 
  Multiple Inheritance != Protocols | Interfaces
 
 I quite agree, but I've done enough Java to know that if they could 
 have solved it with MI, they would have.
 
  Protocols/Interfaces is a way of saying My structure is none of
 your
  damn business, but I comply with the rules you've set.
 
 Yes, exactly.
 
  I disagree, and I hope you've simply swapped terms around.
 
  I think you want to declare I comply with ruleset X at the callee
  object level. That enables the compiler to (1) check that you're
 not
  lying; and (2) optimize based on (1).
 
 At least one of us is using caller/callee in the X11 sense.  What I
 mean and what I think you mean is:
 
   method foo ( Thingie $t ) { ... }
 
   $object-foo( $behaves_like_thingie );
 
 foo() says, Give me something that I can treat like a Thingie.  I 
 don't care HOW it does it, I just want it to do something sane.

To me, $object.Class is the callee (includes method foo). The code
that contains C$object-foo($behaves_like_thingie); is the caller.

 If we're just confused over a bit of terminology, we're in violent 
 agreement on the idea, which is much more important.

Yeah.

So what do we get?

# Multiple Inheritance:
class Combo is all(SuperClass1, SuperClass2, ...) {...}
class Comb2 is Super1 is Super2 {...}

# Protocol: 
# More than just an interface, because Perl6 is okay with 
# loose encapsulation
protocol TCPIP {
  has $.variable;   # Protocol requires this variable
  has $.var2 is Array of Int;   # Ditto
  method Int m1(Int, Str) {...} # Method required
}

Going one step farther, there's a function called protocol and maybe
one called class that handle this sort of thing. Also, Cis means
Cimplements when given a protocol, and Cimplements extracts a
default protocol when given a class.

  class Scalar implements Str
   implements Int
   implements Ref
   {...}  # All you need to know.

  class MyArray is class(Array)  # Convert PCL to Class
 
Perverse behavior:

# Converts protocol TCPIP, above, to anon class, inherits.
class Perv is class(TCPIP) {...} 

# Converts Super2 to Protocol, implements it. 
class Perv2 is Super1 implements Super2 {...}
class Perv2 is Super1 is protocol(Super2) {...}

# Alternatively, select any of:
#   {private, protected, public}_methods (or methods = public)
#   {private, protected, public}_data (data = public)
#   inheritance
class Perv2 is Super1 implements Super2, qw(methods inheritance) {...}
class Perv2 is Super1 is protocol(Super2, qw(methods inheritance))
{...}

=Austin
  


Re: Protocols

2003-07-24 Thread Kurt Starsinic
On Jul 24, David Wheeler wrote:
 On Wednesday, July 23, 2003, at 05:57  PM, chromatic wrote:
 
 The first is a deeper question -- besides inheritance, there's 
 delegation, aggregation, and reimplementation (think mock objects) 
 that can make two classes have equivalent interfaces.  I'd like some 
 way to mark this equivalence *without* having to inherit from an 
 abstract base class and I wish that interface equivalence were checked 
 before inheritance, as per Luke's idea.
 
 Sounds like you want Java-style interfaces to me.

Follow the thread back.  Objective-C had them way first, and their
ur-name is protocols.

- Kurt



Re: Protocols

2003-07-24 Thread Benjamin Goldberg
Chromatic wrote:
[snip]
  I think you want to declare I comply with ruleset X at the callee
  object level. That enables the compiler to (1) check that you're not
  lying; and (2) optimize based on (1).
 
 At least one of us is using caller/callee in the X11 sense.  What I
 mean and what I think you mean is:
 
 method foo ( Thingie $t ) { ... }
 
 $object-foo( $behaves_like_thingie );
 
 foo() says, Give me something that I can treat like a Thingie.  I
 don't care HOW it does it, I just want it to do something sane.
 
 $behaves_like_thingie is an instance of a class that somehow says,
 Hey, I act like Thingie.  I'm substitutable for Thingie if you don't
 break my encapsulation.

If this were Java, the way to do this would be to define a Thingie
interface, and then an (archetypical) ThingieObject class... any time
that we want to actually *create* Thingies, we would use new
ThingieObject, but everywhere else, we would use the typename
Thingie.  This way, when we want a class which acts like a Thingie,
but without inheriting any of it's innards, simply implement the Thingie
interface, instead of inheriting the ThingyObject class.

idea type=wierd
Here's a possible idea -- have a method of the Class class, which
returns (creates) an anonymous Interface object, which provides all of
the public methods of that class, and which is magically one of the
parents of that class.

This way, when one wants to define a new class X which acts like some
other class Y, but which doesn't *really* inherit from Y (none of the
internal data, etc.), we can define X as implementing the Y.interface()
Interface.  For our isa operator, and (perhaps more importantly) for
multimethod dispatch and/or sub prototype checking, we only check if an
object inherits from a class's magic parent interface, and *don't* check
if it *really* inherits from that class itself.
/idea

Of course, this by itself wouldn't let us delegate to the ThingyObject's
versions of the methods... that would require another extra layer of
nonsense^Windirection.


 If we're just confused over a bit of terminology, we're in violent
 agreement on the idea, which is much more important.

-- 
$a=24;split//,240513;s/\B/ = /for@@=qw(ac ab bc ba cb ca
);{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print [EMAIL PROTECTED]
]\n;((6=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))redo;}


Re: Protocols

2003-07-24 Thread chromatic
On Thursday, July 24, 2003, at 05:28 PM, Benjamin Goldberg wrote:

If this were Java, the way to do this would be to define a Thingie
interface, and then an (archetypical) ThingieObject class... any time
that we want to actually *create* Thingies, we would use new
ThingieObject, but everywhere else, we would use the typename
Thingie.  This way, when we want a class which acts like a Thingie,
but without inheriting any of it's innards, simply implement the 
Thingie
interface, instead of inheriting the ThingyObject class.
Yes, that's the Java way to do it.  Surely we can do it better in Perl 
6.

The problem with Java interfaces is that you have to rely on the 
library writer to have expected you to use an interface.  Given the 
amount of CPAN modules that, for example, expect a glob and preclude me 
from passing in an IO::Handle with code like this:

	croak Need a glob unless ref $thingie eq 'GLOB';

I'm not sure that the Java style is helpful.  I'd rather not multiply 
entities needlessly.

For our isa operator, and (perhaps more importantly) for
multimethod dispatch and/or sub prototype checking, we only check if an
object inherits from a class's magic parent interface, and *don't* 
check
if it *really* inherits from that class itself.
heretic
Why should an implementor inherit from the interface?
If inheritance and polymorphic equivalence are two different things, 
they ought to be handled two different ways.  If anything, inheritance 
is a specific case of the general mechanism of marking polymorphic 
equivalence.

Again, the interesting question isn't Does this thing derive from 
something I know about? It's Does this thing support the operations I 
expect it to support?  I don't care how, just that it does.

I don't want to call $mock_foo-isa( 'foo' ) because $mock_foo *isn't* 
a foo.  I don't want to call $delegates_to_foo-isa( 'foo' ) because 
$delegates_to_foo *isn't* a foo.  They can both handle foo-methods, but 
neither is a foo.
/heretic

-- c