Re: YAPC::EU and Perl 6 Roles

2009-07-15 Thread Jon Lang
TSa wrote:
> HaloO,
>
> Jon Lang wrote:
>>
>> Well, yes and no.  The class still has the final say on how a given
>> method is to be implemented; the only thing being debated here is
>> whether or not the class should have to explicitly pull rank to
>> redefine a method being provided by a role, or if it does so silently.
>>  The latter approach is how things currently stand, and is being
>> criticized as a source of bugs as authors of classes inadvertently
>> override method definitions that they didn't intend to override.
>
> I think the distinction can be made implicitly. Methods in a role
> with no implementation are silently overridden. Ones with an
> implementation produce a warning if the composing class overrides
> it without some extra syntax. This bites only the case where the
> role provides a default implementation intended for overriding.

Perhaps.  FWIW, applying the "supersede" keyword to the class method
would work as the "extra syntax" to which you refer.  Your last
sentence is pointing to the distinction that I was trying to make with
the "mandate"/"suggest" pairing.

For clarity, let me propose the following terminology: an "interface"
is a role with methods that suggest their implementations by default;
a "mixin" is a role with methods that mandate their implementations by
default.  I could see adopting one of these terms as a variation on
"role" and treating "role" itself as the other one; if we do this,
which would be preferable: interfaces and roles, or roles and mixins?
That is: when you think "role", do you think of the interface
semantics or the mixin semantics most readily?

-- 
Jonathan "Dataweaver" Lang


Re: YAPC::EU and Perl 6 Roles

2009-07-15 Thread TSa

HaloO,

Jon Lang wrote:

Well, yes and no.  The class still has the final say on how a given
method is to be implemented; the only thing being debated here is
whether or not the class should have to explicitly pull rank to
redefine a method being provided by a role, or if it does so silently.
 The latter approach is how things currently stand, and is being
criticized as a source of bugs as authors of classes inadvertently
override method definitions that they didn't intend to override.


I think the distinction can be made implicitly. Methods in a role
with no implementation are silently overridden. Ones with an
implementation produce a warning if the composing class overrides
it without some extra syntax. This bites only the case where the
role provides a default implementation intended for overriding.

Regards, TSa.
--
"The unavoidable price of reliability is simplicity" -- C.A.R. Hoare
"Simplicity does not precede complexity, but follows it." -- A.J. Perlis
1 + 2 + 3 + 4 + ... = -1/12  -- Srinivasa Ramanujan


Re: YAPC::EU and Perl 6 Roles

2009-07-15 Thread TSa

HaloO,

Jon Lang wrote:

I'd still like to get a synonym for "mandate role", though - a word
that captures the meaning of "unit of behavior".


A bit burdened with conflicting meaning but I think "mixin" is what
you are looking for.


Regards, TSa.
--
"The unavoidable price of reliability is simplicity" -- C.A.R. Hoare
"Simplicity does not precede complexity, but follows it." -- A.J. Perlis
1 + 2 + 3 + 4 + ... = -1/12  -- Srinivasa Ramanujan


Re: YAPC::EU and Perl 6 Roles

2009-07-15 Thread Jon Lang
Raphael Descamps wrote:
> Am Freitag, den 10.07.2009, 17:06 -0700 schrieb Jon Lang:
>> How about this: in role composition, "mandate" causes methods to take
>> precedence over other methods with which they would normally conflict,
>> and to conflict with methods that would normally take precedence over
>> them.
>
> I really dislike this because it is contrary to the original idea of the
> "stateless traits" as defined in the original paper from Nathanael
> Schärli.

Agreed.  OTOH, Roles are already contrary in this respect, because
they can provide attributes as well as methods.  Note also that this
was my first proposal; I have since abandoned it in favor of (I hope)
a more intuitive approach.

> The main reason why "traits" have been introduced was to solve the
> problems inherent to mixins. In mixins the main problem is that the
> class using the mixin is not able to control the composition (which is
> simply done sequencially) and that lend to fragile hierarchies.
>
> The brilliant idea with "traits" is that it bring back the control to
> the class consuming the "trait" and conflicts have to be solved
> explicitly. The traits paper propose 3 different operators to solve such
> conflicts: overriding, excluding or aliasing.
>
> I definitively think that perl 6 roles should also have an excluding
> operator because I think that *every* composition conflicts arising
> should be solvable by the class comsuming the role.
>
> What you propose here is a step behind: you reintroduce the problem
> existing with mixins by bringing back precedence rules in the way
> composition is made.

Well, yes and no.  The class still has the final say on how a given
method is to be implemented; the only thing being debated here is
whether or not the class should have to explicitly pull rank to
redefine a method being provided by a role, or if it does so silently.
 The latter approach is how things currently stand, and is being
criticized as a source of bugs as authors of classes inadvertently
override method definitions that they didn't intend to override.

> So far, I have only seen reference to the original paper decribing the
> "stateless traits". As roles are an implementation of "stateful traits",
> maybe we should start to point to the paper formalising it:
> http://scg.unibe.ch/archive/papers/Berg07eStatefulTraits.pdf

Thanks for the link.

-- 
Jonathan "Dataweaver" Lang


Re: YAPC::EU and Perl 6 Roles

2009-07-15 Thread Raphael Descamps
Am Freitag, den 10.07.2009, 17:06 -0700 schrieb Jon Lang:
> How about this: in role composition, "mandate" causes methods to take
> precedence over other methods with which they would normally conflict,
> and to conflict with methods that would normally take precedence over
> them.

I really dislike this because it is contrary to the original idea of the
"stateless traits" as defined in the original paper from Nathanael
Schärli.
The main reason why "traits" have been introduced was to solve the
problems inherent to mixins. In mixins the main problem is that the
class using the mixin is not able to control the composition (which is
simply done sequencially) and that lend to fragile hierarchies.

The brilliant idea with "traits" is that it bring back the control to
the class consuming the "trait" and conflicts have to be solved
explicitly. The traits paper propose 3 different operators to solve such
conflicts: overriding, excluding or aliasing.

I definitively think that perl 6 roles should also have an excluding
operator because I think that *every* composition conflicts arrising
should be solvable by the class comsuming the role.

What you propose here is a step behind: you reintroduce the problem
existing with mixins by bringing back precedence rules in the way
composition is made.

So far, I have only seen reference to the original paper decribing the
"stateless traits". As roles are an implementation of "stateful traits",
maybe we should start to point to the paper formalising it:
http://scg.unibe.ch/archive/papers/Berg07eStatefulTraits.pdf

>   So:
> 
> role R1 { mandate method foo { ... } }
> role R2 { method foo { ... } }
> class C does R1 does R2 { ... }
> 
> Normally, the compiler would complain of a conflict between R1 and R2;
> but because R1::foo is mandated, it wins out.
> 
> role R { mandate method foo { ... } }
> class C does R { method foo { ... } }
> 
> Normally, C::foo would take precedence over R::foo; but because R::foo
> is mandated, the compiler complains of a conflict between C and R.
> 
> When two methods have the "mandate" keyword, they are compared to each
> other as if neither had the keyword.
> 
> role R { mandate method foo { ... } }
> class C does R { mandate method foo { ... } }
> 
> Since both R::foo and C::foo are mandated, C::foo supersedes R::foo.
> 
> Applying the "mandate" keyword to a role is shorthand for applying it
> to all of its methods.
> 
> mandate role R {
> method foo { ... }
> method bar { ... }
> method baz { ... }
> }
> 
> is the same as:
> 
> role R {
> mandate method foo { ... }
> mandate method bar { ... }
> mandate method baz { ... }
> }
> 
> This behavior can be overridden by the "suggest" keyword:
> 
> mandate role R {
> suggest method foo { ... }
> method bar { ... }
> method baz { ... }
> }
> 
> is the same as:
> 
> role R {
> method foo { ... }
> mandate method bar { ... }
> mandate method baz { ... }
> }
> 
> That is, every method is either mandated or suggested, and suggested
> by default.  Mandating a role changes the default for its methods, or
> you could explicitly suggest the role.  The latter possibility would
> allow for a pragma that changes the role's default importance from
> suggested to mandated.
> 
> Ovid's distinction between interface and unit of behavior could be
> managed by this distinction: "suggest role R" is primarily intended as
> an interface, with behavior being a suggestion only and implicitly
> overriden by the class; "mandate role R" is primarily intended as a
> unit of behavior, and overriding its behavior requires that you
> explicitly supersede it.  In Ovid's programs, he might start by saying
> "use mandate", so that roles operate as units of behavior by default,
> and can be declared as interfaces by saying "suggest role" instead of
> "role".  Or maybe the pragma declares "interface" as a synonym for
> "suggest role".  (I'd be more comfortable with this if I could think
> of a comparable synonym for "mandate role"; at that point, you could
> do away with the pragma - use "role", "suggest role", or "interface"
> to mean "interface", and use "mandate role" or ??? to mean "unit of
> behavior".)
> 
> At this point, you can strengthen the importance of a method (raising
> it from a suggestion to a mandate); but you cannot weaken it.  Thus,
> interfaces can be composed into units of behavior; but not vice versa:
> attempting to do so would result in a unit of behavior.  I think that
> the converse _should_ be possible; but I'm not quite sure how it might
> be done.
> 



Re: YAPC::EU and Perl 6 Roles

2009-07-10 Thread Jon Lang
Jon Lang wrote:
> "supersede" already has a meaning with respect to classes; and what
> I'm thinking of would apply to classes as well as roles; so I'm going
> to suggest another keyword.
>
> How about this: in role composition, "mandate" causes methods to take
> precedence over other methods with which they would normally conflict,
> and to conflict with methods that would normally take precedence over
> them.

Or, perhaps more simply, say that if you "mandate" a method in a role,
you must "supersede" it in whatever you are composing it into in order
to override the definition.  So:

role R { mandate method foo { ... } }
class C does R { supersede method foo { ... } }

I'd still recommend the suggest/mandate pairing, and their application
directly to methods or indirectly via the role; the only change is
that "mandate" be redefined as "Thou Shalt Not Override This/These
Methods..." and "supersede" becomes "...Unless You Really Mean It."
Conflicts still occur as normal when composing multiple roles; the
only catch is that you _have to_ resolve them using a supersede method
if any of the conflicting methods are mandated.

Or maybe not.  Perhaps a conflict between composed roles cancels out
the conflicting method implementations whether or not any of them are
mandates, leaving the class free to define its own version.  That is,
the only time you must "supersede" a method is when you're trying to
override a single "mandate" method.

I'd still like to get a synonym for "mandate role", though - a word
that captures the meaning of "unit of behavior".

-- 
Jonathan "Dataweaver" Lang


Re: YAPC::EU and Perl 6 Roles

2009-07-10 Thread Jon Lang
Larry Wall wrote:
> Dave Whipp wrote:
>> Ovid wrote:
>>
>>> I'd like to see something like this (or whatever the equivalent Perl 6 
>>> syntax would be):
>>>
>>>   class PracticalJoke does Bomb does SomeThingElse {
>>>     method fuse() but overrides { ... }
>>>   }
>>>
>>> The "overrides" tells Perl 6 that we're overriding the fuse() method
>> > from either Bomb or SomeThingElse (or both).  Otherwise, a warning
>> > or exception would be useful to prevent me from accidentally overriding
>> > needed behavior.
>>
>> This would also be useful to catch the case where you mistype the
>> override method, and so have to go debug why you're still using the
>> base-class (or role) version of the method.
>
> Note we already have syntax that can be applied here:
>
>    supersede method fuse {...}
>    augment method fuse {...}
>
> It only remains to spec what those mean... :)

"supersede" already has a meaning with respect to classes; and what
I'm thinking of would apply to classes as well as roles; so I'm going
to suggest another keyword.

How about this: in role composition, "mandate" causes methods to take
precedence over other methods with which they would normally conflict,
and to conflict with methods that would normally take precedence over
them.  So:

role R1 { mandate method foo { ... } }
role R2 { method foo { ... } }
class C does R1 does R2 { ... }

Normally, the compiler would complain of a conflict between R1 and R2;
but because R1::foo is mandated, it wins out.

role R { mandate method foo { ... } }
class C does R { method foo { ... } }

Normally, C::foo would take precedence over R::foo; but because R::foo
is mandated, the compiler complains of a conflict between C and R.

When two methods have the "mandate" keyword, they are compared to each
other as if neither had the keyword.

role R { mandate method foo { ... } }
class C does R { mandate method foo { ... } }

Since both R::foo and C::foo are mandated, C::foo supersedes R::foo.

Applying the "mandate" keyword to a role is shorthand for applying it
to all of its methods.

mandate role R {
method foo { ... }
method bar { ... }
method baz { ... }
}

is the same as:

role R {
mandate method foo { ... }
mandate method bar { ... }
mandate method baz { ... }
}

This behavior can be overridden by the "suggest" keyword:

mandate role R {
suggest method foo { ... }
method bar { ... }
method baz { ... }
}

is the same as:

role R {
method foo { ... }
mandate method bar { ... }
mandate method baz { ... }
}

That is, every method is either mandated or suggested, and suggested
by default.  Mandating a role changes the default for its methods, or
you could explicitly suggest the role.  The latter possibility would
allow for a pragma that changes the role's default importance from
suggested to mandated.

Ovid's distinction between interface and unit of behavior could be
managed by this distinction: "suggest role R" is primarily intended as
an interface, with behavior being a suggestion only and implicitly
overriden by the class; "mandate role R" is primarily intended as a
unit of behavior, and overriding its behavior requires that you
explicitly supersede it.  In Ovid's programs, he might start by saying
"use mandate", so that roles operate as units of behavior by default,
and can be declared as interfaces by saying "suggest role" instead of
"role".  Or maybe the pragma declares "interface" as a synonym for
"suggest role".  (I'd be more comfortable with this if I could think
of a comparable synonym for "mandate role"; at that point, you could
do away with the pragma - use "role", "suggest role", or "interface"
to mean "interface", and use "mandate role" or ??? to mean "unit of
behavior".)

At this point, you can strengthen the importance of a method (raising
it from a suggestion to a mandate); but you cannot weaken it.  Thus,
interfaces can be composed into units of behavior; but not vice versa:
attempting to do so would result in a unit of behavior.  I think that
the converse _should_ be possible; but I'm not quite sure how it might
be done.

-- 
Jonathan "Dataweaver" Lang


Re: YAPC::EU and Perl 6 Roles

2009-07-10 Thread David Green

On 2009-Jul-8, at 1:49 pm, Ovid wrote:
That being said, roles also have two competing uses (though they  
don't conflict as badly).  As units of behavior, they provide the  
functionality your code needs.  However, they can also serve as an  
interface.



Maybe there are Interfaces, which are, well, just interfaces, and  
there are Roles, which are Interfaces plus a partial or full  
implementation.  Like roles and classes, roles and interfaces could be  
transparently interchanged when suitable.  Add some bodies to an  
Interface and you've got a Role; cast a Role to an Interface and you  
strip out everything but the declarations.



Behavioral:  if you are primarily relying on roles to provide  
behavior (as we do at the BBC), then silently discarding the role's  
behavior by providing a method of the same name in your class can  
lead to very confusing bugs.  I've lost a lot of time debugging this  
behavior.



role Stuff
{
suggest method foo { ... }
method bar { ... }
}

class Thing does Stuff
{
method foo { ... }
supersede method bar { ... }
}


Since foo() is only suggested by this role, you can easily override  
it; whereas bar() needs to be explicitly superseded.  (Or maybe it  
should be "method foo :suggested")


The idea being that certain methods are expected to work by accepting  
what's provided in the role most of the time, so you should rarely  
have to supersede them; or they're merely suggestions, and therefore  
you are expected to role^H^H roll your own most of the time.  (And if  
you find yourself getting annoyed that you have to type "supersede" so  
much, that's probably a good clue that something went wrong somewhere  
in the design.)


Either that, or just have suitable warnings that can be toggled on or  
off depending on what sort of policies you need.  That was actually my  
first thought, and I think we should have adjustable warnings for  
everything anyway, but the more I look at the above example, the more  
it's growing on me.



-David



Re: YAPC::EU and Perl 6 Roles

2009-07-08 Thread Larry Wall
On Wed, Jul 08, 2009 at 01:59:53PM -0700, Dave Whipp wrote:
> Ovid wrote:
>
>> I'd like to see something like this (or whatever the equivalent Perl 6 
>> syntax would be):
>>
>>   class PracticalJoke does Bomb does SomeThingElse {
>> method fuse() but overrides { ... }
>>   }
>>
>> The "overrides" tells Perl 6 that we're overriding the fuse() method
> > from either Bomb or SomeThingElse (or both).  Otherwise, a warning
> > or exception would be useful to prevent me from accidentally overriding
> > needed behavior.
>
> This would also be useful to catch the case where you mistype the  
> override method, and so have to go debug why you're still using the
> base-class (or role) version of the method.

Note we already have syntax that can be applied here:

supersede method fuse {...}
augment method fuse {...}

It only remains to spec what those mean... :)

Larry


Re: YAPC::EU and Perl 6 Roles

2009-07-08 Thread Dave Whipp

Ovid wrote:


I'd like to see something like this (or whatever the equivalent Perl 6 syntax 
would be):

  class PracticalJoke does Bomb does SomeThingElse {
method fuse() but overrides { ... }
  }

The "overrides" tells Perl 6 that we're overriding the fuse() method

> from either Bomb or SomeThingElse (or both).  Otherwise, a warning
> or exception would be useful to prevent me from accidentally overriding
> needed behavior.

This would also be useful to catch the case where you mistype the 
override method, and so have to go debug why you're still using the

base-class (or role) version of the method.


Private methods in Roles (Was: Re: YAPC::EU and Perl 6 Roles)

2009-07-08 Thread Daniel Ruoso
Em Qua, 2009-07-08 às 12:49 -0700, Ovid escreveu:
> Behavioral:  if you are primarily relying on roles to provide behavior
> (as we do at the BBC), then silently discarding the role's behavior by
> providing a method of the same name in your class can lead to very
> confusing bugs.  I've lost a lot of time debugging this behavior.

That's actually a tipping point, and I'm thinking we never conceptually
extrapolated the use of Roles to a point that competing Roles in a
composition are bringing methods to the class that are actually relevant
to that roles, but doesn't mix well with the semantics of the composed
class.

Maybe what we need is a way to define methods that are not composed to
the class at all, but are there just for implementation sake. That could
probably mean that methods declared as privates in the role should not
be composed in the class, and the lookup of private methods should honor
the original place of declaration...

daniel



Re: YAPC::EU and Perl 6 Roles

2009-07-08 Thread Ovid

- Original Message 

> From: Jonathan Worthington 

> Ovid wrote:
> > It needs the timed fuse() from a Bomb role and a non-lethal explode() from 
> > a 
> Spouse role, though each role provides both methods.
> I'm curious...
> 
> 1) How often do you in real life find yourself needing to do things like this 
> in 
> real life? This is a sort of strained, if amusing, example. :-)

We use roles very, very heavily.  We've found that the important thing is 
choosing descriptive names.  Thus, we rarely need to exclude methods from roles 
because our names are unambiguous.  The only time I recall us running into this 
problem is when we have two or more methods with identical names which perform 
semantically identical behaviors but need different implementations.
 
> 2) A lot of me wonders if a need to exclude a method from a role is a hint 
> that 
> the role does too many things and should be decomposed into smaller pieces, 
> such 
> that it can be applied in a more "granular" way?

As noted, we only have this happen when the semantics are identical but the 
implementation must differ.  At this point, we really do need a way to exclude 
methods.  This doesn't happen very often, but it's happened enough (probably 
about 10 times in our code base) that a convenient way of handling this would 
be useful.

> I'm curious to hear the experiences of Ovid and others working with roles a 
> lot 
> too. Is this a serious lacking in Perl 6's roles as currently specified, or 
> something that, in being absent, makes people consider their design more? 
> Knowing that will influence the solution we choose, which has options ranging 
> from, "yes, make a neat syntax for it" through "leave it out of the core, and 
> if 
> people want it enough it can be a CPAN module".

Actually, the only serious concern I have (pardon me if you've heard this 
before) is how we silently discard a role's method if the class provides it.  A 
digression is in order.  Some of you know the background behind roles, but not 
everyone.

The problem with classes is that they tend to have two competing uses.  Classes 
are agents of responsibility (which tends to make them grow larger) and, via 
inheritance, are agents of code reuse (which tends to want classes to be 
smaller).  These competing tendencies have been a source of much OO pain and 
roles decouple the behavioral reuse from class responsibility quite nicely.

That being said, roles also have two competing uses (though they don't conflict 
as badly).  As units of behavior, they provide the functionality your code 
needs.  However, they can also serve as an interface.  The behavioral/interface 
divide has already demonstrated a subtle tension in the use of roles in my work.

For those of you who have seen the arguments about this rage on use.perl, my 
apologies :(

Interface:  if you are taking advantage of a role as an interface, it's quite 
useful to have your class provide one or more methods with an identical 
signature to the role and have the role's method silently ignored.

Behavioral:  if you are primarily relying on roles to provide behavior (as we 
do at the BBC), then silently discarding the role's behavior by providing a 
method of the same name in your class can lead to very confusing bugs.  I've 
lost a lot of time debugging this behavior.

I'd like to see something like this (or whatever the equivalent Perl 6 syntax 
would be):

  class PracticalJoke does Bomb does SomeThingElse {
method fuse() but overrides { ... }
  }

The "overrides" tells Perl 6 that we're overriding the fuse() method from 
either Bomb or SomeThingElse (or both).  Otherwise, a warning or exception 
would be useful to prevent me from accidentally overriding needed behavior.  
Again, we've lost a huge amount of time debugging this behavior with 
Moose::Roles and I'd hate to have to do this again with Perl 6.  Your mileage 
may vary :)

Cheers,
Ovid
--
Buy the book - http://www.oreilly.com/catalog/perlhks/
Tech blog- http://use.perl.org/~Ovid/journal/
Twitter  - http://twitter.com/OvidPerl
Official Perl 6 Wiki - http://www.perlfoundation.org/perl6


Re: YAPC::EU and Perl 6 Roles

2009-07-08 Thread Kyle Hasselbacher
On Tue, Jul 7, 2009 at 7:13 AM, Jonathan Worthington wrote:
> (Note to the bored: feel free to beat me to adding something like these last
> two to the spectests...I'm away for the afternoon/evening.)

In r27483, I added these tests to S12-methods/multi.t:

http://dev.pugscode.org/changeset/27483

Kyle.


Re: YAPC::EU and Perl 6 Roles

2009-07-08 Thread Jonathan Worthington

Hi,

Going back to the original question...

Ovid wrote:

It needs the timed fuse() from a Bomb role and a non-lethal explode() from a 
Spouse role, though each role provides both methods.

I'm curious...

1) How often do you in real life find yourself needing to do things like 
this in real life? This is a sort of strained, if amusing, example. :-)


2) A lot of me wonders if a need to exclude a method from a role is a 
hint that the role does too many things and should be decomposed into 
smaller pieces, such that it can be applied in a more "granular" way?


I'm curious to hear the experiences of Ovid and others working with 
roles a lot too. Is this a serious lacking in Perl 6's roles as 
currently specified, or something that, in being absent, makes people 
consider their design more? Knowing that will influence the solution we 
choose, which has options ranging from, "yes, make a neat syntax for it" 
through "leave it out of the core, and if people want it enough it can 
be a CPAN module".


Thanks,

Jonathan



Re: YAPC::EU and Perl 6 Roles

2009-07-08 Thread Jonathan Worthington

Jon Lang wrote:

Jonathan Worthington wrote:
  

Ovid wrote:


Though I have issues with Jonathan's approach (I don't like classes
silently discarding role methods as this has caused us many bugs at the
BBC), it's much cleaner that what I see here.
  

s/Jonathan's approach/Perl 6's approach/ # at least, so far as I understand
Perl 6



No; I think he meant "Jonathan's approach", as in the suggestion that
I made earlier about disambiguating by exclusion.

  

Oh, sorry. ETOOMANYJONATHANS. ;-)


It occurs to me that "but" might be a way to approach this, since the
linguistic purpose of that operator is to generate a class or role
that is a slight departure from an existing role:

   A but without(&foo)
  
might generate an anonymous role that's exactly like A except that it

doesn't have the foo method; you could then say something like:

  role A { method foo() { }; method bar() { }; method baz() { } }
  role B { method foo() { }; method bar() { }; method baz () { } }
  class C does A but without(foo, bar) does B but without(baz) { }

  
But C composes in a role to a copy of the object, so it's not 
really following the semantics we want here, and also means we need to 
make without mean something special other than just being a role name. 
And we'd have to tinker quite a bit with the way trait_mod: parses 
to make it handle this. I guess we could do that somehow, but it feels 
odd. Also, trying to look up &foo - which would be in a completely 
separate role - is going to be odd too. It feels like we're making far 
too many things mean something a bit different.


More fitting to me would be an adverb to the does trait modifier...

class C does R1 :without does R2 :without { ... }

The thing is that in this case, does the class actually do R1 and R2? If 
you are going to derive an anonymous role with the methods missing, then 
answer is "no". That is, C ~~ R1 would be false. So I think it'd need to 
act as a modifier to the action of composition, rather than a 
modification to the thing that we're composing.



I agree that there are dangers involved in excluding methods from a
role; thus my use of fairly lengthy phrases in order to accomplish it
- a sort of "handle with care" warning.

  
I wonder if we'd want to mandate that a method of the name must come 
from _somewhere_ otherwise it's an error. At least then you get a 
promise that a method of that name exists...which is about all that "it 
does this role" tells you as an interface contract anyway.



Alternatively, I could see a version of this exclusionary policy being
done through method delegation, by means of the whatever splat -
something like:

  class C {
  has A $a handles * - (foo, bar);
  has B $b handles * - baz;
  }

  
The RHS of the handles is something we smart-match the method name 
against (unless it's one of the special syntactic cases). And thus if 
you care about performance you probably don't want to be falling back to 
handles to do your role composition, since it's kind of the "last 
resort" after we've walked the MRO and found nothing. Anyway, you'd put 
something on the RHS maybe like:


has A $a handles none()

But I'm not sure that will fall through to B for anything that A doesn't 
define other than those two. You'd perhaps just get a dispatch error if 
you said A handles everything but those and it didn't. So it'd probably 
look more like...


has A $.a handles all(any(A.^methods>>.name), none());

Which you almost certainly don't want to be writing. ;-)

Jonathan


Re: YAPC::EU and Perl 6 Roles

2009-07-08 Thread Jon Lang
Jonathan Worthington wrote:
> Ovid wrote:
>> Though I have issues with Jonathan's approach (I don't like classes
>> silently discarding role methods as this has caused us many bugs at the
>> BBC), it's much cleaner that what I see here.
>
> s/Jonathan's approach/Perl 6's approach/ # at least, so far as I understand
> Perl 6

No; I think he meant "Jonathan's approach", as in the suggestion that
I made earlier about disambiguating by exclusion.

It occurs to me that "but" might be a way to approach this, since the
linguistic purpose of that operator is to generate a class or role
that is a slight departure from an existing role:

   A but without(&foo)

might generate an anonymous role that's exactly like A except that it
doesn't have the foo method; you could then say something like:

  role A { method foo() { }; method bar() { }; method baz() { } }
  role B { method foo() { }; method bar() { }; method baz () { } }
  class C does A but without(foo, bar) does B but without(baz) { }

I agree that there are dangers involved in excluding methods from a
role; thus my use of fairly lengthy phrases in order to accomplish it
- a sort of "handle with care" warning.

Alternatively, I could see a version of this exclusionary policy being
done through method delegation, by means of the whatever splat -
something like:

  class C {
  has A $a handles * - (foo, bar);
  has B $b handles * - baz;
  }

-- 
Jonathan "Dataweaver" Lang


Re: YAPC::EU and Perl 6 Roles

2009-07-08 Thread Jonathan Worthington

Ovid wrote:

- Original Message 
  

From: Timothy S. Nelson 

class PracticalJoke {
has Bomb $bomb handles ;
has Spouse $spouse handles ;
}

Note that I have no idea where (if anywhere) the type goes in this. 
Hopefully someone will correct me here.  Note that this does not use the roles 
as roles; it uses them punned as classes.  But it does what you asked :).




Though I have issues with Jonathan's approach (I don't like classes silently discarding role methods as this has caused us many bugs at the BBC), it's much cleaner that what I see here.  
s/Jonathan's approach/Perl 6's approach/ # at least, so far as I 
understand Perl 6


Jonathan



Re: YAPC::EU and Perl 6 Roles

2009-07-08 Thread Timothy S. Nelson

On Wed, 8 Jul 2009, Ovid wrote:

Note that I have no idea where (if anywhere) the type goes in this. 
Hopefully someone will correct me here.  Note that this does not use the roles 
as roles; it uses them punned as classes.  But it does what you asked :).



Though I have issues with Jonathan's approach (I don't like classes silently 
discarding role methods as this has caused us many bugs at the BBC), it's 
much cleaner that what I see here.  You see, with Jonathan's, you only have 
to provide methods for what you're disambiguating, It seems like your code 
would require that I specifically list every method which is handled, which 
would clearly get unwieldy with large roles or many roles.  Did I miss 
something?


	I agree that's a problem, and hopefully one that should be solved. 
The solution I offered solves only your immediate problem.


:)


-
| Name: Tim Nelson | Because the Creator is,|
| E-mail: wayl...@wayland.id.au| I am   |
-

BEGIN GEEK CODE BLOCK
Version 3.12
GCS d+++ s+: a- C++$ U+++$ P+++$ L+++ E- W+ N+ w--- V- 
PE(+) Y+>++ PGP->+++ R(+) !tv b++ DI D G+ e++> h! y-

-END GEEK CODE BLOCK-



Re: YAPC::EU and Perl 6 Roles

2009-07-08 Thread Ovid

- Original Message 
> From: Timothy S. Nelson 
>
> class PracticalJoke {
> has Bomb $bomb handles ;
> has Spouse $spouse handles ;
> }
> 
> Note that I have no idea where (if anywhere) the type goes in this. 
> Hopefully someone will correct me here.  Note that this does not use the 
> roles 
> as roles; it uses them punned as classes.  But it does what you asked :).


Though I have issues with Jonathan's approach (I don't like classes silently 
discarding role methods as this has caused us many bugs at the BBC), it's much 
cleaner that what I see here.  You see, with Jonathan's, you only have to 
provide methods for what you're disambiguating, It seems like your code would 
require that I specifically list every method which is handled, which would 
clearly get unwieldy with large roles or many roles.  Did I miss something?
 
Cheers,
Ovid
--
Buy the book - http://www.oreilly.com/catalog/perlhks/
Tech blog- http://use.perl.org/~Ovid/journal/
Twitter  - http://twitter.com/OvidPerl
Official Perl 6 Wiki - http://www.perlfoundation.org/perl6


Re: YAPC::EU and Perl 6 Roles

2009-07-07 Thread Timothy S. Nelson

On Tue, 7 Jul 2009, Ovid wrote:


 role Bomb {
   method fuse (){ say '3 .. 2 .. 1 ..' }
   method explode () { say 'Rock falls. Everybody dies!' }
 }

 role Spouse {
   method fuse (){ sleep rand(20); say "Now!" }
   method explode () { say 'You worthless piece of junk! Why I should ...' }
 }

 class PracticalJoke does Bomb does Spouse {
 }


class PracticalJoke {
has Bomb $bomb handles ;
has Spouse $spouse handles ;
}

	Note that I have no idea where (if anywhere) the type goes in this. 
Hopefully someone will correct me here.  Note that this does not use the roles 
as roles; it uses them punned as classes.  But it does what you asked :).


:)


-
| Name: Tim Nelson | Because the Creator is,|
| E-mail: wayl...@wayland.id.au| I am   |
-

BEGIN GEEK CODE BLOCK
Version 3.12
GCS d+++ s+: a- C++$ U+++$ P+++$ L+++ E- W+ N+ w--- V- 
PE(+) Y+>++ PGP->+++ R(+) !tv b++ DI D G+ e++> h! y-

-END GEEK CODE BLOCK-



Re: YAPC::EU and Perl 6 Roles

2009-07-07 Thread Jonathan Worthington

Brandon S. Allbery KF8NH wrote:

On Jul 7, 2009, at 08:13 , Jonathan Worthington wrote:

Brandon S. Allbery KF8NH wrote:
I was trying to figure out how to do it with nextsame, but that's 
not looking very simple.


On the other hand, if they were multis then they get added to the 
multi candidate list and therefore you can nextsame into them. Again 
from Rakudo:


> role R { multi method b() { say "lol in role" } }
> class C does R { multi method b() { say "oh hai in class"; nextsame 
} }

> C.new.b
oh hai in class
lol in role


But even then that's only half of it; we want a() from one role and 
b() from another, when both roles do a() and b().  Looks painful to me.


Right, and deference is the Wrong Tool For The Job in that case. The 
right answer is more like:


class C does R1 does R2 {
   method a() { self.R1::a() }
   method b() { self.R2::b() }
}

Thanks,

Jonathan


Re: YAPC::EU and Perl 6 Roles

2009-07-07 Thread Brandon S. Allbery KF8NH

On Jul 7, 2009, at 08:13 , Jonathan Worthington wrote:

Brandon S. Allbery KF8NH wrote:
I was trying to figure out how to do it with nextsame, but that's  
not looking very simple.


On the other hand, if they were multis then they get added to the  
multi candidate list and therefore you can nextsame into them. Again  
from Rakudo:


> role R { multi method b() { say "lol in role" } }
> class C does R { multi method b() { say "oh hai in class";  
nextsame } }

> C.new.b
oh hai in class
lol in role



But even then that's only half of it; we want a() from one role and  
b() from another, when both roles do a() and b().  Looks painful to me.


--
brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allb...@kf8nh.com
system administrator [openafs,heimdal,too many hats] allb...@ece.cmu.edu
electrical and computer engineering, carnegie mellon universityKF8NH




PGP.sig
Description: This is a digitally signed message part


Re: YAPC::EU and Perl 6 Roles

2009-07-07 Thread Jonathan Worthington

Brandon S. Allbery KF8NH wrote:

On Jul 7, 2009, at 07:34 , Jonathan Worthington wrote:

Jon Lang wrote:

I believe that the official word is to say:

 class PracticalJoke does Bomb does Spouse {
   method fuse () { Bomb::fuse }
   method explode () { Spouse::explode }
 }


This way won't work, because:

* It's doing a sub call to something that's a method
* The lookup won't work unless the method has "our" (package) scope *
* Even in that case, the invocant isn't being passed so you'll get a 
"wrong number of parameters" error


I was trying to figure out how to do it with nextsame, but that's not 
looking very simple.



Interesting thought, but the problem is that:

role R { method a() { }; method b() { } }
class C does R { method b() { } }

In this case, method b from the role never gets composed into the class, 
thanks to the method b in the class. (This is the flattening aspect of 
role composition at work). In fact, the composed method behaves pretty 
much as if it had been defined in the class itself. So the method b in 
the role doesn't exist in the candidate list that we walk when doing 
deference. From Rakudo:


> role R { method a() { }; method b() { } }
> class C does R { method b() { } }
> say C.WALK(:name).elems
1

On the other hand, if they were multis then they get added to the multi 
candidate list and therefore you can nextsame into them. Again from Rakudo:


> role R { multi method b() { say "lol in role" } }
> class C does R { multi method b() { say "oh hai in class"; nextsame } }
> C.new.b
oh hai in class
lol in role

And role ones beat parents in the ordering too...

> role R { multi method b() { say "lol in role"; nextsame } }
> class P { method b() { say "parent ftw" } }
> class C is P does R { multi method b() { say "oh hai in class"; 
nextsame } }

> C.new.b
oh hai in class
lol in role
parent ftw

(Note to the bored: feel free to beat me to adding something like these 
last two to the spectests...I'm away for the afternoon/evening.)


Thanks,

Jonathan


Re: YAPC::EU and Perl 6 Roles

2009-07-07 Thread Brandon S. Allbery KF8NH

On Jul 7, 2009, at 07:34 , Jonathan Worthington wrote:

Jon Lang wrote:

I believe that the official word is to say:

 class PracticalJoke does Bomb does Spouse {
   method fuse () { Bomb::fuse }
   method explode () { Spouse::explode }
 }


This way won't work, because:

* It's doing a sub call to something that's a method
* The lookup won't work unless the method has "our" (package) scope *
* Even in that case, the invocant isn't being passed so you'll get a  
"wrong number of parameters" error



I was trying to figure out how to do it with nextsame, but that's not  
looking very simple.


--
brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allb...@kf8nh.com
system administrator [openafs,heimdal,too many hats] allb...@ece.cmu.edu
electrical and computer engineering, carnegie mellon universityKF8NH




PGP.sig
Description: This is a digitally signed message part


Re: YAPC::EU and Perl 6 Roles

2009-07-07 Thread Jonathan Worthington

Jon Lang wrote:

I believe that the official word is to say:

  class PracticalJoke does Bomb does Spouse {
method fuse () { Bomb::fuse }
method explode () { Spouse::explode }
  }
  

This way won't work, because:

* It's doing a sub call to something that's a method
* The lookup won't work unless the method has "our" (package) scope *
* Even in that case, the invocant isn't being passed so you'll get a 
"wrong number of parameters" error


Thanks,

Jonathan

* I somewhat suspect calling a routine in a role using the role name as 
a namespace identifier should be banned anyway, since we'd have no clue 
what to do with references to $?CLASS, which is meant to be generic.




Re: YAPC::EU and Perl 6 Roles

2009-07-07 Thread Jonathan Worthington

Ovid wrote:
Giving a talk about roles at YAPC::EU in Lisbon 

Hey, me too! :-)


and I'm a bit stuck on how to translate a Perl 5 example into Perl 6.  Basically, Imagine 
a "PracticalJoke" class which has fuse() and explode methods().  It needs the 
timed fuse() from a Bomb role and a non-lethal explode() from a Spouse role, though each 
role provides both methods.  In Moose, it's easy:

  package PracticalJoke;
  use Moose;
  with 'Bomb'   => { excludes => 'explode' };
   'Spouse' => { excludes => 'fuse' };

Try as I might, I can't figure out how to translate that into Perl 6.  I have 
the following:

  role Bomb {
method fuse (){ say '3 .. 2 .. 1 ..' }
method explode () { say 'Rock falls. Everybody dies!' }
  }

  role Spouse {
method fuse (){ sleep rand(20); say "Now!" }
method explode () { say 'You worthless piece of junk! Why I should ...' }
  }

  class PracticalJoke does Bomb does Spouse {
  }

Nothing I see in S14 (http://perlcabal.org/syn/S14.html) seems to cover this case. I 
can't declare them as multis as they have the same signature.  There's a note that one 
can "simply to write a class method that overrides the conflicting role methods, 
perhaps figuring out which role method to call", but I don't understand how a 
particular role's methods would be called here.

  
The spec is right in that you need to write a method in the class that 
decides what to do. This will look something like:


   method fuse() { self.Bomb::fuse() }

Or also if you like you can probably get away with:

   method fuse() { $.Bomb::fuse() }

But be aware that then you're forcing item context on the return value.

Note that this is NYI in Rakudo, but I hope to do it fairly soon (before 
YAPC::EU).


Thanks,

Jonathan


Re: YAPC::EU and Perl 6 Roles

2009-07-07 Thread Jon Lang
On Tue, Jul 7, 2009 at 2:48 AM,
Ovid wrote:
>
> Giving a talk about roles at YAPC::EU in Lisbon and I'm a bit stuck on how to 
> translate a Perl 5 example into Perl 6.  Basically, Imagine a "PracticalJoke" 
> class which has fuse() and explode methods().  It needs the timed fuse() from 
> a Bomb role and a non-lethal explode() from a Spouse role, though each role 
> provides both methods.  In Moose, it's easy:
>
>  package PracticalJoke;
>  use Moose;
>  with 'Bomb'   => { excludes => 'explode' };
>       'Spouse' => { excludes => 'fuse' };
>
> Try as I might, I can't figure out how to translate that into Perl 6.  I have 
> the following:
>
>  role Bomb {
>    method fuse ()    { say '3 .. 2 .. 1 ..' }
>    method explode () { say 'Rock falls. Everybody dies!' }
>  }
>
>  role Spouse {
>    method fuse ()    { sleep rand(20); say "Now!" }
>    method explode () { say 'You worthless piece of junk! Why I should ...' }
>  }
>
>  class PracticalJoke does Bomb does Spouse {
>  }
>
> Nothing I see in S14 (http://perlcabal.org/syn/S14.html) seems to cover this 
> case. I can't declare them as multis as they have the same signature.  
> There's a note that one can "simply to write a class method that overrides 
> the conflicting role methods, perhaps figuring out which role method to 
> call", but I don't understand how a particular role's methods would be called 
> here.
>

I believe that the official word is to say:

  class PracticalJoke does Bomb does Spouse {
method fuse () { Bomb::fuse }
method explode () { Spouse::explode }
  }

Personally, I agree that some sort of ability to exclude individual
methods from Roles, such as what Moose does, would be beneficial; but
this is an old argument that has been hashed out many times before.

-- 
Jonathan "Dataweaver" Lang


YAPC::EU and Perl 6 Roles

2009-07-07 Thread Ovid

Giving a talk about roles at YAPC::EU in Lisbon and I'm a bit stuck on how to 
translate a Perl 5 example into Perl 6.  Basically, Imagine a "PracticalJoke" 
class which has fuse() and explode methods().  It needs the timed fuse() from a 
Bomb role and a non-lethal explode() from a Spouse role, though each role 
provides both methods.  In Moose, it's easy:

  package PracticalJoke;
  use Moose;
  with 'Bomb'   => { excludes => 'explode' };
   'Spouse' => { excludes => 'fuse' };

Try as I might, I can't figure out how to translate that into Perl 6.  I have 
the following:

  role Bomb {
method fuse (){ say '3 .. 2 .. 1 ..' }
method explode () { say 'Rock falls. Everybody dies!' }
  }

  role Spouse {
method fuse (){ sleep rand(20); say "Now!" }
method explode () { say 'You worthless piece of junk! Why I should ...' }
  }

  class PracticalJoke does Bomb does Spouse {
  }

Nothing I see in S14 (http://perlcabal.org/syn/S14.html) seems to cover this 
case. I can't declare them as multis as they have the same signature.  There's 
a note that one can "simply to write a class method that overrides the 
conflicting role methods, perhaps figuring out which role method to call", but 
I don't understand how a particular role's methods would be called here.

Cheers,
Ovid
--
Buy the book - http://www.oreilly.com/catalog/perlhks/
Tech blog- http://use.perl.org/~Ovid/journal/
Twitter  - http://twitter.com/OvidPerl
Official Perl 6 Wiki - http://www.perlfoundation.org/perl6