RE: supply and demand (was: Roles and Mix-ins?)

2004-01-07 Thread Jonathan Lang
Austin Hastings wrote:
> Jonathan Lang wrote:
> > OK: when you call $spot.bark, Trog looks for a "bark" method; it finds
> > two: Tree::bark and Dog::bark.  Since both methods have been supplied
> > by roles, $spot has no idea which one to use, and throws an exception 
> > to that effect.  
> 
> I am uncomfortable with this. My understanding has been that the will be
> a compile time error, caught when the class declaration is made. Has 
> that changed recently?

I don't know for certain; but I think so.  Given the ambiguities that can
crop up with multiple dispatches and signatures, it may not be feasable to
catch all of them at compile-time.  

> > As such, the code given above is incorrect.  Adjusting for this error,
> > we rewrite Trog as follows:
> >
> >   class Trog does Tree but no bark does Dog {
> > method grow() {...};
> >   };
> 
> Modulo syntax, this is more right, yes.

I'm not familiar with modulo.  Also, I'm probably abusing the "but" syntax
like nobody's business here.  

> > But in the case of
> >
> >   role Dog {
> > method bark() {...}
> > must bark();
> > method threaten must bark() { bark; }
> >   }
> >
> >   class Toothless does Dog but no threaten() no bark() {
> >   }
> >
> > You'd still have a problem, because even excluding threaten doesn't
> > exclude Dog's demand to be able to bark.
> 
> "Hit jist haint a dawg ifn hit dont bark."

You've never met my dog.  

> But large roles are going to want to say C just once, since (1)
> that makes for easier, more legible documentation; and (2) if chromatic 
> is correct, most functionality with roles (smaller than classes, recall)
> will likely be pretty incestuous.

The "must" clause in the above "threaten" method is redundant, an artifact
of cut-n-paste coding.  The example would work exactly the same with or
without it.  

=
Jonathan "Dataweaver" Lang

__
Do you Yahoo!?
Yahoo! Hotjobs: Enter the "Signing Bonus" Sweepstakes
http://hotjobs.sweepstakes.yahoo.com/signingbonus


RE: supply and demand (was: Roles and Mix-ins?)

2004-01-07 Thread Austin Hastings
From: Jonathan Lang [mailto:[EMAIL PROTECTED]
> Austin Hastings wrote:
> > Jonathan Lang wrote:
> > > Austin Hastings wrote:
> > > > There's two ways to look at that. One way is to say: "I'm going to
> > > > define an interface as being this OTHER thing minus a method." That
> > > > seems like a positive construction, and supporting it might be
> > > > desirable.
> > > >
> > > > The other way is to say: "Nobody knows what methods call what other
> > > > methods in their implementation (nor should we know). Therefore,
> > > > removing methods is forbidden. If you have a conflict of methods,
> > > > alias them and provide support in the knowledge that any component
> > > > C that requires the method may call it internally."
> > >
> > > Or you could say that when you "exclude" a method, what you're really
> > > doing is hiding it from everything external to where it's declared,
> > > while leaving it available to be called internally.  Method exclusion
> > > would be more like declaring a private method in C++ than actually
> > > removing it from the class or role.  This means that a method wouldn't
> > > be provided to a class that C its role but excludes it itself,
> > > and thus it wouldn't be used to satisfy the requirements of any other
> > > roles that the class C.
> >
> > Huh? If it's available to be called internally, you've got the same
> > problem (we were talking about conflict resolution earlier, I think) --
> > that you need to know which one to call.
> >
> > But if you say "there ain't no bark", either we should complain that
> > doing a Dog or a Tree demands it, or we should catch the exception at
> > compile or run time. I'm in favor of the first solution -- you must
> > provide one -- since that seems to be more in keeping with the general
> > "role philosophy" that Larry's been emitting.
>
> Ah; I think I see the confusion.  You're conflating methods that a role
> supplies with methods that a role demands.
>
> Consider this:
>
>   role Tree {
> method bark() {...};
> must grow(); # Tree doesn't have a grow method,
>  # but its class will have to have one.
>   };
>
>   role Dog {
> method bark() {...};
> must grow();
>   };
>
>   class Trog does Tree does Dog {
>   };
>
>   my Trog $spot;
>   $spot.bark; # what happens?
>   $spot.grow; # what happens?
>

First, my understanding is that there's a shared requirement (must grow) and
a name conflict. Before this can compile, we'll need to provide a grow()
method, and we'll need to disambiguate the bark method: there can be only
one. Larry and the paper are pretty clear on this point.

So I'm thinking

  class Trog does Tree does Dog { bark => dogBark } {
method grow {...};
  }

> OK: when you call $spot.bark, Trog looks for a "bark" method; it finds
> two: Tree::bark and Dog::bark.  Since both methods have been supplied by
> roles, $spot has no idea which one to use, and throws an exception to that
> effect.

I am uncomfortable with this. My understanding has been that the will be a
compile time error, caught when the class declaration is made. Has that
changed recently?

> When you call $spot.grow, however, Trog finds _no_ methods; Dog doesn't
> supply a grow method, and neither does Tree.  You get a compile-time error
> to the effect of "incomplete class declaration - missing a grow method."

I sort-of agree. I don't think it requires a call to grow for the compile
time error -- I think it's a declaration time error. (I suppose that the
declarator could provide a "secret" {...} declaration for all required
methods, but what value does this have?)

> As such, the code given above is incorrect.  Adjusting for this error, we
> rewrite Trog as follows:
>
>   class Trog does Tree but no bark does Dog {
> method grow() {...};
>   };

Modulo syntax, this is more right, yes.

> Now when we call $spot.bark, it finds Dog::bark but not Tree::bark;
> therefore, it barks like a dog.

Yep.

> When we call $spot.grow, it finds Trog::grow, but there's still no
> Dog::grow or Tree::grow for it to find; so it grows as only a Trog can.

Yep.

> Things get more interesting when one role demands a method and another
> role supplies it:
>
>   role Tree {
> method bark;
>   }
>
>   role Dog {
> must bark;
> method threaten { bark; }
>   }
>
>   class Trog does Tree does Dog {
>   }
>
>   my Trog $spot;
>   $spot.threaten; # what happens?
>
> When $spot.threaten is called, Trog only finds Dog::threaten, and thus
> calls it.  Dog::threaten then calls $spot.bark; Trog finds a Tree::bark
> method and nothing else, so $spot barks like a Tree.

Right. This seems sensible.

> In other words, when a method supplied by a role calls another method,
> that call gets dispatched to whatever class that role is a part of.
>
> Combining this example with the first one:
>
>   role Tree {
> method bark() {...};
> must grow(); # Tree doesn't have a grow method,
>  # but its class will have to have one.
>   };
>

Re: Roles and Mix-ins?

2004-01-07 Thread Piers Cawley
"Joe Gottman" <[EMAIL PROTECTED]> writes:
> - Original Message - 
> From: "Luke Palmer" <[EMAIL PROTECTED]>
> To: <[EMAIL PROTECTED]>
> Sent: Tuesday, January 06, 2004 4:51 AM
> Subject: [perl] Re: Roles and Mix-ins?
>
>
>> David Storrs writes:
>> >
>> > On Sat, Dec 13, 2003 at 11:12:31AM -0800, Larry Wall wrote:
>> > > On Sat, Dec 13, 2003 at 04:57:17AM -0700, Luke Palmer wrote:
>> >
>> > > : For one, one role's methods don't silently override another's.
> Instead,
>> > > : you get, er, role conflict and you have to disambiguate yourself.
>> >
>> > How do you disambiguate?
>>
>> Let's see...
>>
>> role Dog {
>> method bark() { print "Ruff!" }
>> }
>> role Tree {
>> method bark() { print "Rough!" }
>> }
>> class Trog
>>   does Dog does Tree {
>> method bark() { .Dog::bark() }
>>   }
>> }
>>
>> Perhaps something like that.  In any case, you do it by putting the
>> offending method directly in the aggregating class.
>>
>
>How about something like
> class Trog
>does Dog {bark=>dogBark} does Tree {bark=>treeBark}
>{...}
>
> Then we could have code like
>   my Trog $foo = Trog.new();
>   my Dog $spot :=  $foo;
>   my Tree $willow := $foo;
>   $spot.bark(); # calls dogBark()
>   $willow.bark(); #calls treeBark()
>
>This works better when Dog::bark and Tree::bark are both needed but they
> do different things.

I'm really not happy with the idea that simply using a typed variable
should change the way a method call on that variable is
dispatched. You seem to be saying that

 class Parent { override { "Parent" }}
 class Child is Parent { override { "Child" }}

 my $kid = Child.new;

 my Parent $dad := $kid;
 
 print $kid.override; # "Child"
 print $dad.override; # "Parent"

And down that road lies C++ and other insanity.

-- 
Beware the Perl 6 early morning joggers -- Allison Randal


Re: Roles and Mix-ins?

2004-01-07 Thread Piers Cawley
Jonathan Lang <[EMAIL PROTECTED]> writes:

> Luke Palmer wrote:
>> Renaming methods defeats the purpose of roles.  Roles are like
>> interfaces inside-out.  They guarantee a set of methods -- an interface
>> -- except they provide the implementation to (in terms of other,
>> required methods).  Renaming the method destroys the interface
>> compatibility.
>
> Not so.  A role is more than an inside-out interface; it guarantees a set
> of methods either by calling it an error to not define a given method in a
> class that C the role or by defining the method itself.  In the
> latter case, renaming the method can be quite useful; even in the former
> case, renaming or excluding methods from a role is useful if you want an
> interface which is almost, but not quite, like the one that the role
> provides.  

And examples of doing all of that are given in the original Traits
paper (and, for that matter, in the summary of Traits/Roles that I
wrote up for the summary.)

-- 
Beware the Perl 6 early morning joggers -- Allison Randal


supply and demand (was: Roles and Mix-ins?)

2004-01-07 Thread Jonathan Lang
Austin Hastings wrote:
> Jonathan Lang wrote:
> > Austin Hastings wrote:
> > > There's two ways to look at that. One way is to say: "I'm going to
> > > define an interface as being this OTHER thing minus a method." That
> > > seems like a positive construction, and supporting it might be
> > > desirable.
> > >
> > > The other way is to say: "Nobody knows what methods call what other
> > > methods in their implementation (nor should we know). Therefore,
> > > removing methods is forbidden. If you have a conflict of methods,
> > > alias them and provide support in the knowledge that any component 
> > > C that requires the method may call it internally."
> >
> > Or you could say that when you "exclude" a method, what you're really
> > doing is hiding it from everything external to where it's declared,
> > while leaving it available to be called internally.  Method exclusion 
> > would be more like declaring a private method in C++ than actually 
> > removing it from the class or role.  This means that a method wouldn't
> > be provided to a class that C its role but excludes it itself, 
> > and thus it wouldn't be used to satisfy the requirements of any other 
> > roles that the class C.
> 
> Huh? If it's available to be called internally, you've got the same
> problem (we were talking about conflict resolution earlier, I think) -- 
> that you need to know which one to call.
> 
> But if you say "there ain't no bark", either we should complain that
> doing a Dog or a Tree demands it, or we should catch the exception at 
> compile or run time. I'm in favor of the first solution -- you must 
> provide one -- since that seems to be more in keeping with the general 
> "role philosophy" that Larry's been emitting.

Ah; I think I see the confusion.  You're conflating methods that a role
supplies with methods that a role demands.  

Consider this: 

  role Tree {
method bark() {...}; 
must grow(); # Tree doesn't have a grow method, 
 # but its class will have to have one.  
  };
  
  role Dog {
method bark() {...}; 
must grow(); 
  };

  class Trog does Tree does Dog {
  };

  my Trog $spot; 
  $spot.bark; # what happens?
  $spot.grow; # what happens?

OK: when you call $spot.bark, Trog looks for a "bark" method; it finds
two: Tree::bark and Dog::bark.  Since both methods have been supplied by
roles, $spot has no idea which one to use, and throws an exception to that
effect.  

When you call $spot.grow, however, Trog finds _no_ methods; Dog doesn't
supply a grow method, and neither does Tree.  You get a compile-time error
to the effect of "incomplete class declaration - missing a grow method." 
As such, the code given above is incorrect.  Adjusting for this error, we
rewrite Trog as follows: 

  class Trog does Tree but no bark does Dog {
method grow() {...};
  };

Now when we call $spot.bark, it finds Dog::bark but not Tree::bark;
therefore, it barks like a dog.  

When we call $spot.grow, it finds Trog::grow, but there's still no
Dog::grow or Tree::grow for it to find; so it grows as only a Trog can.  

Things get more interesting when one role demands a method and another
role supplies it: 

  role Tree {
method bark; 
  }

  role Dog {
must bark; 
method threaten { bark; }
  }

  class Trog does Tree does Dog {
  }

  my Trog $spot;
  $spot.threaten; # what happens?

When $spot.threaten is called, Trog only finds Dog::threaten, and thus
calls it.  Dog::threaten then calls $spot.bark; Trog finds a Tree::bark
method and nothing else, so $spot barks like a Tree.  

In other words, when a method supplied by a role calls another method,
that call gets dispatched to whatever class that role is a part of.  

Combining this example with the first one: 

  role Tree {
method bark() {...}; 
must grow(); # Tree doesn't have a grow method, 
 # but its class will have to have one.  
  };
  
  role Dog {
method bark() {...}; 
must grow(); 
method threaten { bark; }
  };
  
  class Trog does Tree does Dog but no bark {
method grow() {...};
  };
  
  my Trog $spot; 
  $spot.threaten; # what happens?

When $spot.threaten is called, Trog only finds a Dog::threaten() method,
and dispatches the call to it; it in turn calls $spot.bark; Trog finds a
Tree::bark but not a Dog::bark (because the bark that would normally be
supplied by Dog was suppressed by Trog).  There's no ambiguity, so $spot
barks like a Tree.  

So what would happen in the following situation:

  role Dog {
method bark() {...}; 
method threaten { bark; }
  };

  class Toothless does Dog but no bark {
  }

  my Toothless $rover; 
  $rover.threaten; 

$rover.threaten calls $rover.bark; #Toothless then looks for a bark
method...

...and doesn't find one.  Hmm...

This is only a problem because one of Dog's methods calls the bark method;
doing so implicitly causes the role to demand that method on a conceptual
basis.  Any attribute or method that is used by any of a role's sup

RE: Roles and Mix-ins?

2004-01-06 Thread Austin Hastings


From: Jonathan Lang [mailto:[EMAIL PROTECTED]
> Austin Hastings wrote:
> > There's two ways to look at that. One way is to say: "I'm going to
> > define an interface as being this OTHER thing minus a method." That
> > seems like a positive construction, and supporting it might be
> > desirable.
> >
> > The other way is to say: "Nobody knows what methods call what other
> > methods in their implementation (nor should we know). Therefore,
> > removing methods is forbidden. If you have a conflict of methods, alias
> > them and provide support in the knowledge that any component C
> > that requires the method may call it internally."
>
> Or you could say that when you "exclude" a method, what you're really
> doing is hiding it from everything external to where it's declared, while
> leaving it available to be called internally.  Method exclusion would be
> more like declaring a private method in C++ than actually removing it from
> the class or role.  This means that a method wouldn't be provided to a
> class that C its role but excludes it itself, and thus it wouldn't
> be used to satisfy the requirements of any other roles that the class
> C.

Huh? If it's available to be called internally, you've got the same problem
(we were talking about conflict resolution earlier, I think) -- that you
need to know which one to call.

So you alias one (Dog::bark) to dogBark, which leaves Tree::bark as the
default "bark". This is fine.

But if you say "there ain't no bark", either we should complain that doing a
Dog or a Tree demands it, or we should catch the exception at compile or run
time. I'm in favor of the first solution -- you must provide one -- since
that seems to be more in keeping with the general "role philosophy" that
Larry's been emitting.

The notion of "I'm defining it to be {...}" is an interesting one -- you're
explicitly discussing it, so obviously you've thought about it. But it's not
there. I wonder if it wouldn't be easier to say {fail} instead?

=Austin



RE: Roles and Mix-ins?

2004-01-06 Thread Jonathan Lang
Austin Hastings wrote:
> There's two ways to look at that. One way is to say: "I'm going to
> define an interface as being this OTHER thing minus a method." That 
> seems like a positive construction, and supporting it might be 
> desirable.
> 
> The other way is to say: "Nobody knows what methods call what other
> methods in their implementation (nor should we know). Therefore, 
> removing methods is forbidden. If you have a conflict of methods, alias 
> them and provide support in the knowledge that any component C 
> that requires the method may call it internally."

Or you could say that when you "exclude" a method, what you're really
doing is hiding it from everything external to where it's declared, while
leaving it available to be called internally.  Method exclusion would be
more like declaring a private method in C++ than actually removing it from
the class or role.  This means that a method wouldn't be provided to a
class that C its role but excludes it itself, and thus it wouldn't
be used to satisfy the requirements of any other roles that the class
C.  

=
Jonathan "Dataweaver" Lang

__
Do you Yahoo!?
Yahoo! Hotjobs: Enter the "Signing Bonus" Sweepstakes
http://hotjobs.sweepstakes.yahoo.com/signingbonus


Re: Roles and Mix-ins?

2004-01-06 Thread Jonathan Lang
Joe Gottman wrote:
> Luke Palmer wrote:
> > Your renaming can be done easily enough, and more clearly (IMO) with:
> >
> >   class Trog
> > does Dog does Tree {
> >   method bark() { ... }   # Explicitly remove the provided method
> >   method dogBark()  { .Dog::bark() }
> >   method treeBark() { .Tree::bark() }
> >   }
> 
>But won't explicitly removing bark() from the class also disable
> Dog::bark() and Tree::bark() for the class?  

No.  method bark isn't technically being removed; rather, method
Trog::bark is being defined as "postpone the definition" while
simultaneously taking precedence over both Dog::bark and Tree::bark, since
it is a class method native to Trog while the others are role methods
provided to Trog - and class methods take precedence over role methods. 
So if "my Trog $spot; $spot.bark;" is executed, perl will unambiguously
call $spot.Trog::bark, and then complain that it hasn't been defined. 
(This assumes that it doesn't complain during compile-time.)

This works, but seems counterintuitive to me.  

=
Jonathan "Dataweaver" Lang

__
Do you Yahoo!?
Yahoo! Hotjobs: Enter the "Signing Bonus" Sweepstakes
http://hotjobs.sweepstakes.yahoo.com/signingbonus


RE: Roles and Mix-ins?

2004-01-06 Thread Austin Hastings


From: Jonathan Lang [mailto:[EMAIL PROTECTED]
> Luke Palmer wrote:
> > Renaming methods defeats the purpose of roles.  Roles are like
> > interfaces inside-out.  They guarantee a set of methods -- an interface
> > -- except they provide the implementation to (in terms of other,
> > required methods).  Renaming the method destroys the interface
> > compatibility.
>
> Not so.  A role is more than an inside-out interface; it guarantees a set
> of methods either by calling it an error to not define a given method in a
> class that C the role or by defining the method itself.  In the
> latter case, renaming the method can be quite useful; even in the former
> case, renaming or excluding methods from a role is useful if you want an
> interface which is almost, but not quite, like the one that the role
> provides.

There's two ways to look at that. One way is to say: "I'm going to define an
interface as being this OTHER thing minus a method." That seems like a
positive construction, and supporting it might be desirable.

The other way is to say: "Nobody knows what methods call what other methods
in their implementation (nor should we know). Therefore, removing methods is
forbidden. If you have a conflict of methods, alias them and provide support
in the knowledge that any component C that requires the method may
call it internally."

I'm in favor of the second approach, myself. If you alias away all of the
(e.g.) C methods, you must provide a replacement.

=Austin



Re: Roles and Mix-ins?

2004-01-06 Thread Joe Gottman

- Original Message - 
From: "Luke Palmer" <[EMAIL PROTECTED]>
To: "Joe Gottman" <[EMAIL PROTECTED]>
Cc: "Perl6" <[EMAIL PROTECTED]>
Sent: Tuesday, January 06, 2004 9:34 PM
Subject: [perl] Re: Roles and Mix-ins?


> Joe Gottman writes:
> >
> > - Original Message - 
> > From: "Luke Palmer" <[EMAIL PROTECTED]>
> > To: <[EMAIL PROTECTED]>
> > Sent: Tuesday, January 06, 2004 4:51 AM
> > Subject: [perl] Re: Roles and Mix-ins?
> >
> >
> > > David Storrs writes:
> > > >
> > > > On Sat, Dec 13, 2003 at 11:12:31AM -0800, Larry Wall wrote:
> > > > > On Sat, Dec 13, 2003 at 04:57:17AM -0700, Luke Palmer wrote:
> > > >
> > > > > : For one, one role's methods don't silently override another's.
> > Instead,
> > > > > : you get, er, role conflict and you have to disambiguate
yourself.
> > > >
> > > > How do you disambiguate?
> > >
> > > Let's see...
> > >
> > > role Dog {
> > > method bark() { print "Ruff!" }
> > > }
> > > role Tree {
> > > method bark() { print "Rough!" }
> > > }
> > > class Trog
> > >   does Dog does Tree {
> > > method bark() { .Dog::bark() }
> > >   }
> > > }
> > >
> > > Perhaps something like that.  In any case, you do it by putting the
> > > offending method directly in the aggregating class.
> > >
> >
> >How about something like
> > class Trog
> >does Dog {bark=>dogBark} does Tree {bark=>treeBark}
> >{...}
> >
> > Then we could have code like
> >   my Trog $foo = Trog.new();
> >   my Dog $spot :=  $foo;
> >   my Tree $willow := $foo;
> >   $spot.bark(); # calls dogBark()
> >   $willow.bark(); #calls treeBark()
> >
> >This works better when Dog::bark and Tree::bark are both needed but
they
> > do different things.
>
> Renaming methods defeats the purpose of roles.  Roles are like
> interfaces inside-out.  They guarantee a set of methods -- an interface
> -- except they provide the implementation to (in terms of other,
> required methods).  Renaming the method destroys the interface
> compatibility.
>
> Your renaming can be done easily enough, and more clearly (IMO) with:
>
> class Trog
>   does Dog does Tree {
> method bark() { ... }   # Explicitly remove the provided method
> method dogBark()  { .Dog::bark() }
> method treeBark() { .Tree::bark() }
> }

   But won't explicitly removing bark() from the class also disable
Dog::bark() and Tree::bark() for the class?  Renaming would work if other
methods in Dog are directed to dogBark() when they call bark(), and other
methods in Tree are redirected to treeBark().

Joe Gottman





Re: Roles and Mix-ins?

2004-01-06 Thread Jonathan Lang
Luke Palmer wrote:
> Renaming methods defeats the purpose of roles.  Roles are like
> interfaces inside-out.  They guarantee a set of methods -- an interface
> -- except they provide the implementation to (in terms of other,
> required methods).  Renaming the method destroys the interface
> compatibility.

Not so.  A role is more than an inside-out interface; it guarantees a set
of methods either by calling it an error to not define a given method in a
class that C the role or by defining the method itself.  In the
latter case, renaming the method can be quite useful; even in the former
case, renaming or excluding methods from a role is useful if you want an
interface which is almost, but not quite, like the one that the role
provides.  

=
Jonathan "Dataweaver" Lang

__
Do you Yahoo!?
Yahoo! Hotjobs: Enter the "Signing Bonus" Sweepstakes
http://hotjobs.sweepstakes.yahoo.com/signingbonus


Re: Roles and Mix-ins?

2004-01-06 Thread Jonathan Lang
Joe Gottman wrote:
>How about something like
> class Trog
>does Dog {bark=>dogBark} does Tree {bark=>treeBark}
>{...}
> 
> Then we could have code like
>   my Trog $foo = Trog.new();
>   my Dog $spot :=  $foo;
>   my Tree $willow := $foo;
>   $spot.bark(); # calls dogBark()
>   $willow.bark(); #calls treeBark()
> 
>This works better when Dog::bark and Tree::bark are both needed but
> they do different things.

I'm not sure about the syntax, but it does a great job of illustrating the
aliasing approach to disambiguation.  The exclusion approach might be
something like: 

class Trog
   does Dog 
   does Tree but no bark
   {...}

so that, as far as class Trog is concerned, there I no bark method for
Tree.  

That is, include a pair of traits[1]: "no" and "alias", where "no"
modifies the class to remove the specified attributes and/or methods, and
where "alias" modifies the class to rename the specified attribute or
method; then apply those traits to the roles in question as if they were
properties[2], creating singleton roles that are used to compose the
class.  This would require "but" to have a higher precedence than "is" or
"does", but I think that that might actually make sense.  

The only drawback to this is that I don't see the "no" and "alias" traits
being useful except as properties: you exclude a method from a class
simply by not defining it in the first place; and if you want to use a
different name for a given method, you simply use the different name for
it.  Then again, you could probably use "no" to implement something akin
to C++'s "private", where the method excluded by "no" is merely excluded
from use outside the class, while other class methods could see and use it
normally.  I suppose that a similar line of reasoning would technically
apply to alias; but it's beyond my ability to see how forcing a method to
be known by a different name by non-class methods than it is by class
methods could possibly be useful.  

Meanwhile, Luke was essentially pointing out that class methods take
precedence over role methods, and role methods I be accessed by
explicitly specifying which role to use; so specifying a class method with
the same name as ambiguous role methods but which explicitly calls one of
them would also remove the ambiguity.  

[1] by "trait", I'm referring to a thing (which might or might not be like
a role but probably isn't) which is applied to a class via C and which
modifies the standard rules for how the class behaves.  The more I look at
traits, the more I'm seeing them as being more sub-like than role-like:
they're defined more in terms of what they do to the class than what they
provide to the class.  

[2] by "property", I'm referring to a role that is applied to a class via
C, resulting in a new singleton class that C the original class
and C the new role.  This differs from previous (and currently
official) use of the term in that I do I assume that the role in
question has exactly one attribute.  If someone can come up with a better
term for "something like an official property, but more general", I'd be
more than happy to adopt its use instead.  


=
Jonathan "Dataweaver" Lang

__
Do you Yahoo!?
Yahoo! Hotjobs: Enter the "Signing Bonus" Sweepstakes
http://hotjobs.sweepstakes.yahoo.com/signingbonus


Re: Roles and Mix-ins?

2004-01-06 Thread Luke Palmer
Joe Gottman writes:
> 
> - Original Message - 
> From: "Luke Palmer" <[EMAIL PROTECTED]>
> To: <[EMAIL PROTECTED]>
> Sent: Tuesday, January 06, 2004 4:51 AM
> Subject: [perl] Re: Roles and Mix-ins?
> 
> 
> > David Storrs writes:
> > >
> > > On Sat, Dec 13, 2003 at 11:12:31AM -0800, Larry Wall wrote:
> > > > On Sat, Dec 13, 2003 at 04:57:17AM -0700, Luke Palmer wrote:
> > >
> > > > : For one, one role's methods don't silently override another's.
> Instead,
> > > > : you get, er, role conflict and you have to disambiguate yourself.
> > >
> > > How do you disambiguate?
> >
> > Let's see...
> >
> > role Dog {
> > method bark() { print "Ruff!" }
> > }
> > role Tree {
> > method bark() { print "Rough!" }
> > }
> > class Trog
> >   does Dog does Tree {
> > method bark() { .Dog::bark() }
> >   }
> > }
> >
> > Perhaps something like that.  In any case, you do it by putting the
> > offending method directly in the aggregating class.
> >
> 
>How about something like
> class Trog
>does Dog {bark=>dogBark} does Tree {bark=>treeBark}
>{...}
> 
> Then we could have code like
>   my Trog $foo = Trog.new();
>   my Dog $spot :=  $foo;
>   my Tree $willow := $foo;
>   $spot.bark(); # calls dogBark()
>   $willow.bark(); #calls treeBark()
> 
>This works better when Dog::bark and Tree::bark are both needed but they
> do different things.

Renaming methods defeats the purpose of roles.  Roles are like
interfaces inside-out.  They guarantee a set of methods -- an interface
-- except they provide the implementation to (in terms of other,
required methods).  Renaming the method destroys the interface
compatibility.

Your renaming can be done easily enough, and more clearly (IMO) with:

class Trog 
  does Dog does Tree {
method bark() { ... }   # Explicitly remove the provided method
method dogBark()  { .Dog::bark() }
method treeBark() { .Tree::bark() }
}

Luke



Re: Roles and Mix-ins?

2004-01-06 Thread Joe Gottman

- Original Message - 
From: "Luke Palmer" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Tuesday, January 06, 2004 4:51 AM
Subject: [perl] Re: Roles and Mix-ins?


> David Storrs writes:
> >
> > On Sat, Dec 13, 2003 at 11:12:31AM -0800, Larry Wall wrote:
> > > On Sat, Dec 13, 2003 at 04:57:17AM -0700, Luke Palmer wrote:
> >
> > > : For one, one role's methods don't silently override another's.
Instead,
> > > : you get, er, role conflict and you have to disambiguate yourself.
> >
> > How do you disambiguate?
>
> Let's see...
>
> role Dog {
> method bark() { print "Ruff!" }
> }
> role Tree {
> method bark() { print "Rough!" }
> }
> class Trog
>   does Dog does Tree {
> method bark() { .Dog::bark() }
>   }
> }
>
> Perhaps something like that.  In any case, you do it by putting the
> offending method directly in the aggregating class.
>

   How about something like
class Trog
   does Dog {bark=>dogBark} does Tree {bark=>treeBark}
   {...}

Then we could have code like
  my Trog $foo = Trog.new();
  my Dog $spot :=  $foo;
  my Tree $willow := $foo;
  $spot.bark(); # calls dogBark()
  $willow.bark(); #calls treeBark()

   This works better when Dog::bark and Tree::bark are both needed but they
do different things.

Joe Gottman





Re: Roles and Mix-ins?

2004-01-06 Thread Luke Palmer
David Storrs writes:
> 
> On Sat, Dec 13, 2003 at 11:12:31AM -0800, Larry Wall wrote:
> > On Sat, Dec 13, 2003 at 04:57:17AM -0700, Luke Palmer wrote:
> 
> > : For one, one role's methods don't silently override another's.  Instead,
> > : you get, er, role conflict and you have to disambiguate yourself.  
> 
> How do you disambiguate?

Let's see...

role Dog {
method bark() { print "Ruff!" }
}
role Tree {
method bark() { print "Rough!" }
}
class Trog 
  does Dog does Tree {
method bark() { .Dog::bark() }
  }
}

Perhaps something like that.  In any case, you do it by putting the
offending method directly in the aggregating class.

> After reading this several times, I _think_ I understand.  Let me
> check: imagine that the original class is a text buffer going from
> 0-99.  We have two roles (A and B), each of length 100.  Objects of
> various types can then see different segments of the buffer (i.e.,
> different methods/properties/whatever), as follows:
> 
>   TypeCan see 
>   ---
>   Class   1-100   
>   A   101-199
>   B   200-299
>   Class+A 1-100,101-199
>   Class+B 1-100,200-299
>   Class+A+B   1-100,101-199,200-299
> 
> Is that right?

Umm... I'm not sure that's what I'd use roles for.  And I'm not sure how
roles with associated data are supposed to work yet.  But I think you
have the general idea.

Luke


Re: Roles and Mix-ins?

2004-01-05 Thread Jonathan Lang
David Storrs wrote:
> On Sat, Dec 13, 2003 at 11:12:31AM -0800, Larry Wall wrote:
> > On Sat, Dec 13, 2003 at 04:57:17AM -0700, Luke Palmer wrote:
> > : For one, one role's methods don't silently override another's. 
> > : Instead, you get, er, role conflict and you have to disambiguate 
> > : yourself.  
> 
> How do you disambiguate?

For most cases, you either alias or exclude one or the other of the
offending methods from the final class, rendering the ambiguity moot. 
However, role conflict not disambiguiated in either of the above manners
throws an exception (presumably with a list of the ambiguous methods),
letting you write code to disambiguate in whatever manner you like on a
case-by-case basis.  The only question I have about such an exception is
what sort of information your ambiguity handler code receives.  


=
Jonathan "Dataweaver" Lang

__
Do you Yahoo!?
Find out what made the Top Yahoo! Searches of 2003
http://search.yahoo.com/top2003


Re: Roles and Mix-ins?

2004-01-05 Thread David Storrs

On Sat, Dec 13, 2003 at 11:12:31AM -0800, Larry Wall wrote:
> On Sat, Dec 13, 2003 at 04:57:17AM -0700, Luke Palmer wrote:

> : For one, one role's methods don't silently override another's.  Instead,
> : you get, er, role conflict and you have to disambiguate yourself.  

How do you disambiguate?

> : For
> : two, you can attach new roles to an object at runtime (I don't know if
> : you can do this with mixins, actually).
> 
> Yes, you can.  The mixin creates a new singleton class every time
> you do it, derived from the previous class.  My current thinking is
> that run-time roles work a little differently.  You get a singleton
> class for the object the first time you apply a property, so that each
> object's properties remain distinct.  However, subsequent properties
> re-use the existing singleton class, and do the same role-conflict
> checks at run time that "does" would do in the class definition
> at compile time.  Furthermore, the singleton class is not really
> derived from the original class, but just presents a different view
> of the same class, so that, from the viewpoint of the object, every
> role has the same standing, and run-time roles aren't privileged
> above compile-time roles, as they would be if the singleton class
> were really derived from the original class.  In a sense, the object
> thinks it's recomposing the original class, but it's slightly wrong.

After reading this several times, I _think_ I understand.  Let me
check: imagine that the original class is a text buffer going from
0-99.  We have two roles (A and B), each of length 100.  Objects of
various types can then see different segments of the buffer (i.e.,
different methods/properties/whatever), as follows:

TypeCan see 
---
Class   1-100   
A   101-199
B   200-299
Class+A 1-100,101-199
Class+B 1-100,200-299
Class+A+B   1-100,101-199,200-299

Is that right?

Dave


Re: Roles and Mix-ins?

2003-12-13 Thread Larry Wall
On Sat, Dec 13, 2003 at 04:57:17AM -0700, Luke Palmer wrote:
: Chris Shawmail (E-mail) writes:
: > I'm still digesting the vocabulary thread, but while I do, let me ask a
: > question that's probably crystal clear to everyone else.
: > 
: > Do roles act as a form of mix-in, as Ruby modules may, and Objective-C
: > protocols do?
: > 
: > Would the following two snippets be at all equivalent?
: 
: Probably, depending on what's in the eventual definition of Foo.
: 
: Roles are quite similar to mixins (as the Traits paper said that they
: were inspired by mixins), but they're distinctly not the same. 
: 
: For one, one role's methods don't silently override another's.  Instead,
: you get, er, role conflict and you have to disambiguate yourself.  For
: two, you can attach new roles to an object at runtime (I don't know if
: you can do this with mixins, actually).

Yes, you can.  The mixin creates a new singleton class every time
you do it, derived from the previous class.  My current thinking is
that run-time roles work a little differently.  You get a singleton
class for the object the first time you apply a property, so that each
object's properties remain distinct.  However, subsequent properties
re-use the existing singleton class, and do the same role-conflict
checks at run time that "does" would do in the class definition
at compile time.  Furthermore, the singleton class is not really
derived from the original class, but just presents a different view
of the same class, so that, from the viewpoint of the object, every
role has the same standing, and run-time roles aren't privileged
above compile-time roles, as they would be if the singleton class
were really derived from the original class.  In a sense, the object
thinks it's recomposing the original class, but it's slightly wrong.

If you really want new roles to override old roles, it's easy enough
to throw a real derivation in there.  But the Traits paper argues,
and I'm inclined to agree with them, that this not what you want for
the default behavior.  Now the Traits paper was really only worrying
about composing classes at compile time, and we're extending it to
run-time.  That means you can get name collisions at run time when
you add a role.  I still think it's better to catch that sort of goof
earlier than later.  That means the syntax for C may evolve to
look more like the syntax for C.  Whatever that looks like...

Larry


Re: Roles and Mix-ins?

2003-12-13 Thread Luke Palmer
Chris Shawmail (E-mail) writes:
> I'm still digesting the vocabulary thread, but while I do, let me ask a
> question that's probably crystal clear to everyone else.
> 
> Do roles act as a form of mix-in, as Ruby modules may, and Objective-C
> protocols do?
> 
> Would the following two snippets be at all equivalent?

Probably, depending on what's in the eventual definition of Foo.

Roles are quite similar to mixins (as the Traits paper said that they
were inspired by mixins), but they're distinctly not the same. 

For one, one role's methods don't silently override another's.  Instead,
you get, er, role conflict and you have to disambiguate yourself.  For
two, you can attach new roles to an object at runtime (I don't know if
you can do this with mixins, actually).

> # Perl6
> role Talk {
>method say_hello {
>   print "Hello world!\n"
>}
> }
> 
> class Foo does Talk { ... }
> 
> Foo.new.say_hello;
> 
> # Ruby
> module Talk
>def say_hello
>   puts "Hello world!"
>end
> end
> 
> class Foo
>include Talk
> end
> 
> Foo.new.say_hello

Luke



Roles and Mix-ins?

2003-12-13 Thread Chris Shawmail (E-mail)
I'm still digesting the vocabulary thread, but while I do, let me ask a
question that's probably crystal clear to everyone else.

Do roles act as a form of mix-in, as Ruby modules may, and Objective-C
protocols do?

Would the following two snippets be at all equivalent?

# Perl6
role Talk {
   method say_hello {
  print "Hello world!\n"
   }
}

class Foo does Talk { ... }

Foo.new.say_hello;

# Ruby
module Talk
   def say_hello
  puts "Hello world!"
   end
end

class Foo
   include Talk
end

Foo.new.say_hello

---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.545 / Virus Database: 339 - Release Date: 11/27/2003