Re: YAPC::EU and Perl 6 Roles

2009-07-08 Thread Ovid

- Original Message 
 From: Timothy S. Nelson wayl...@wayland.id.au

 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-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 Jonathan Worthington

Ovid wrote:

- Original Message 
  

From: Timothy S. Nelson wayl...@wayland.id.au

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 Jon Lang
Jonathan Worthingtonjonat...@jnthn.net 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

Jon Lang wrote:

Jonathan Worthingtonjonat...@jnthn.net 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 Cbut 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:does 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 :withoutfoo bar does R2 :withoutbaz { ... }

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(foo bar)

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(foo bar));

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

Jonathan


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



Reusing code: Everything but the kitchen sink

2009-07-08 Thread Jon Lang
Jonathan Worthington wrote in YAPC::EU and Perl 6 Roles:
 More fitting to me would be an adverb to the does trait modifier...

 class C does R1 :withoutfoo bar does R2 :withoutbaz { ... }

 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.

Moving the adverb from the role to the trait modifier would still
violate the notion that C ~~ R1; so it doesn't actually gain us
anything.  Instead, consider the following possibility: R1
:withoutfoo bar is a separate but related role from R1.  The
implicit relationship between them is that R1 ~~ R1 :withoutfoo bar.
 So C ~~ R1 would be false; but C ~~ R1 :withoutfoo bar would be
true.

 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.

Right.  Another way to handle this without establishing reverse-does
relationships that I describe above would be to say that the adverb
doesn't actually remove the method in question; it just suppresses its
implementation.  That is, given:

role R1 {
method foo() { say foo }
}

class C does :blockingfoo R1 { ... }

this would compose R1 into C, but would discard the implementation of
R1::foo while doing so.

In the spirit of TIMTOWTDI, both approaches could be available:

R1 :withoutfoo acts as an anonymous role that R1 implicitly does,
and which is set up almost exactly like R1 except that it doesn't have
method foo.  This could have other uses besides role composition, such
as expanding a web of roles from the specific to the general.

C does :blockingfoo R1 composes R1 into C, but discards foo's
implementation while doing so.

 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.

You're right, but for a different reason.  Perl 6 has three techniques
for code reuse, which I refer to as the be, do, have triad:

Class inheritance (to be): 'is C;'
Role composition (to do): 'does R;'
Attribute delegation (to have): 'has A $a handles foo;'

Just on a conceptual level, you don't want to fall back on attribute
delegation in order to emulate role composition.  Still, there are
uses for delegating to all or most of an attribute's methods.

 Anyway, you'd put something on the RHS maybe
 like:

 has A $a handles none(foo bar)

 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(foo bar));

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

Right; which is why I was looking for a more abbreviated form.  If we
go with the idea that we're using a Set on the RHS, then '*' could be
shorthand for 'Set($a.^methods)', and 'Set::infix:-' could be the
Set Difference operator, with the item, list, or set on the RHS being
excluded from the LHS.  So:

$a handles * - foo bar

would be short for something like:

$a handles Set($a.^methods) - Set(foo, bar)

This use of the Whatever splat is similar to its use in a list index,
where '*' behaves as if it were the list's element count.

--

Looking this over, I note that the only code reuse mechanism for which
we haven't looked at the everything except... concept is class
inheritance.  OTOH, I think that the blocking tool that works for role
composition could be adapted for use with class inheritence as well:

Class C is :blockingfoo bar C1 is :blockingbaz C2 { ... }

That is, if you were to search the class heierarchy for foo, it would
skip the C1 branch in its search.  This would have to be treated with
care, because it would mean that C doesn't inherit everything from C1.
 This _would_ break the anything you can do I can do, too nature of
class inheritence; but I'm not sure how big of a crime that is.  Perl
generally discourages the use of class hierarchies, and it certainly
isn't the preferred means of type-checking.  And maybe you could get
around this by having the isa predicate return a more involved
response than 

Re: YAPC::EU and Perl 6 Roles

2009-07-08 Thread Kyle Hasselbacher
On Tue, Jul 7, 2009 at 7:13 AM, Jonathan Worthingtonjonat...@jnthn.net 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 Ovid

- Original Message 

 From: Jonathan Worthington jonat...@jnthn.net

 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


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 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.


r27485 - docs/Perl6/Spec/S32-setting-library

2009-07-08 Thread pugs-commits
Author: moritz
Date: 2009-07-08 23:41:43 +0200 (Wed, 08 Jul 2009)
New Revision: 27485

Modified:
   docs/Perl6/Spec/S32-setting-library/Numeric.pod
Log:
[S32/Num] log's base is positional

Modified: docs/Perl6/Spec/S32-setting-library/Numeric.pod
===
--- docs/Perl6/Spec/S32-setting-library/Numeric.pod 2009-07-08 19:45:10 UTC 
(rev 27484)
+++ docs/Perl6/Spec/S32-setting-library/Numeric.pod 2009-07-08 21:41:43 UTC 
(rev 27485)
@@ -129,7 +129,7 @@
 
 =item log
 
- our Num multi method log ( Num $x: Num :$base = Num::e ) is export
+ our Num multi method log ( Num $x: Num $base = Num::e ) is export
 
 Logarithm of base C$base, default Natural. Calling with C$x == 0 is an
 error.



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


Roles discussion

2009-07-08 Thread Jonathan Worthington

Hi all,

It's been interesting to participate in the roles discussion so far, and 
I'm happy to see there's a lot of interest in getting the right options 
and the right defaults. I'm leaving tomorrow morning on vacation, and 
will be mostly offline for a week or so (the alps are quite a 
distraction...). So I just wanted to note that my lack of further 
comments for a while aren't at all lack of interest. Just so nobody is 
wondering. :-)


Thanks!

Jonathan


r27487 - docs/Perl6/Spec

2009-07-08 Thread pugs-commits
Author: lwall
Date: 2009-07-09 02:36:00 +0200 (Thu, 09 Jul 2009)
New Revision: 27487

Modified:
   docs/Perl6/Spec/S14-roles-and-parametric-types.pod
Log:
[S14] a slightly closer approximation to eventual reality


Modified: docs/Perl6/Spec/S14-roles-and-parametric-types.pod
===
--- docs/Perl6/Spec/S14-roles-and-parametric-types.pod  2009-07-08 22:20:01 UTC 
(rev 27486)
+++ docs/Perl6/Spec/S14-roles-and-parametric-types.pod  2009-07-09 00:36:00 UTC 
(rev 27487)
@@ -15,8 +15,8 @@
 
 Created: 24 Feb 2009 (extracted from S12-objects.pod)
 
-Last Modified: 26 Jun 2009
-Version: 7
+Last Modified: 8 Jul 2009
+Version: 8
 
 =head1 Overview
 
@@ -357,8 +357,8 @@
 
 role xxx {
 has Int $.xxx;
-multi trait_mod:is(::?CLASS $declarand where {!.defined}, xxx 
$trait, $arg?) {...}
-multi trait_mod:is(Any $declarand, xxx $trait, $arg?) {...}
+multi trait_mod:is(::?CLASS $declarand where {!.defined}, :$xxx!) 
{...}
+multi trait_mod:is(Any $declarand, :$xxx!) {...}
 }
 
 Then it can function as a trait.  A well-behaved trait handler will say
@@ -370,19 +370,19 @@
 matching, you can also say:
 
 class MyBase {
-multi trait_mod:is(MyBase $declarand where {!.defined}, MyBase 
$base, $arg?) {...}
-multi trait_mod:is(Any $declarand, MyBase $tied, $arg?) {...}
+multi trait_mod:is(MyBase $declarand where {!.defined}, MyBase 
$base) {...}
+multi trait_mod:is(Any $declarand, MyBase $tied) {...}
 }
 
 These capture control if CMyBase wants to capture control of how it gets
 used by any class or container.  But usually you can just let it call
 the generic defaults:
 
-multi trait_mod:is($declarand where {!.defined}, $base, $arg?) {...}
+multi trait_mod:is($declarand where {!.defined}, $base) {...}
 
 which adds C$base to the isa list of class C$declarand, or
 
-multi trait_mod:is(Any $declarand, $tied, $arg?) {...}
+multi trait_mod:is(Any $declarand, $tied) {...}
 
 which sets the tie type of the container declarand to the implementation type
 in C$tied.
@@ -395,8 +395,8 @@
 Here's Cwill, which (being syntactic sugar) merely delegates to
 back to is:
 
-multi sub trait_mod:will($declarand, $trait, arg) {
-trait_mod:is($declarand, $trait, arg);
+multi sub trait_mod:will($declarand, :$trait) {
+trait_mod:is($declarand, :$trait);
 }
 
 Other traits are applied with a single word, and require special