Re: This week's summary

2004-01-06 Thread Andy Wardley
Uri Guttman wrote:
 i say we just sell them a license to use the US constitution. 

Bill Gates wrote:
 What is it with these Linux guys?
 i say we just sell them a license to use Windoze.

:-)

A




RE: This week's summary

2004-01-06 Thread Peter Scott
In article [EMAIL PROTECTED],
 [EMAIL PROTECTED] (Austin Hastings) writes:

PS: While I'm somewhat sympathetic to the fact that eu guys are trying to
spin up 200 years worth of amendments and supreme court decisions at the
same time, it's still a ratf*ck. Eu need to get eurselves a Larry.

Just put Damian on it, and there'll be a Lingua::EU::ConstitutionGenerator
by Christmas.  Probably with a back door making him king with droit du 
seigneur option in perpetuity.

-- 
Peter Scott
http://www.perldebugged.com/
*** NEW *** http//www.perlmedic.com/




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
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 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 Iis 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 Ican 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 Cis 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
Cbut, resulting in a new singleton class that Cis the original class
and Cdoes the new role.  This differs from previous (and currently
official) use of the term in that I do Inot 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 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 Cdoes 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 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 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 Cdoes 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 Crole 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.) Cbark methods, you must provide a replacement.

=Austin



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 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 Crole 
 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 Cdoes its role but excludes it itself, and thus it wouldn't
be used to satisfy the requirements of any other roles that the class
Cdoes.  

=
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]
 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 Crole
  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 Cdoes its role but excludes it itself, and thus it wouldn't
 be used to satisfy the requirements of any other roles that the class
 Cdoes.

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



A modest question

2004-01-06 Thread Austin Hastings

Larry, chromatic, Allison, Damian, et al:

What's the big fascination with traits?

I read the paper, and at the end where they talked about refactoring the
Smalltalk class library, they managed to claim 12% fewer lines of code:

 In total, these classes use 46 different traits and implement 509 methods,
 whereof 36 are automatically generated accessor methods. This is just over
 5% fewer methods than in the original implementation. In addition, the
code
 for the trait implementation is 12% smaller than the original.

However, the authors continue to report:

 This is especially remarkable because 10% of the methods in the original
 implementation are implemented “too high” in the hierarchy specifically to
 enable code sharing. With inheritance, the penalty for this is the
repeated
 need to cancel inherited behaviour (using methods that cause a runtime
 error) in subclasses where they do not make sense. In the trait
 implementation, there is no need to resort to this tactic.

Which I interpret as meaning that the artificially high code-sharing
implementations have caused extra lines of code in lower level classes. So
the 12% figure is inclusive of deliberate pessimization that has been done
to substitute clarity for compactness -- presumably native code that
hasn't been evolved so much would have more compactness, less redundant
code, and would yield less than 12% improvement by refactoring into the
traits model.

So on the grand balance of utility, what are the metrics that traits are
supposed to help improve? The 10% reduction of LOC reminds me of the old
Assembler rule of thumb: do it last, you'll get 10% faster.

Presumably there are some other metrics being improved. Can one or more of
you explain what the perceived improvements, and what's the order of
significance? That is, give us a 1. 2. 3. list?

Thanks,

=Austin



Re: A modest question

2004-01-06 Thread chromatic
On Tue, 2004-01-06 at 22:26, Austin Hastings wrote:

 So on the grand balance of utility, what are the metrics that traits are
 supposed to help improve?

Two big ones:

- naming collections of behavior that are too fine-grained to fit into
classes cleanly
- enabling finer-grained code reuse

Consider a method that needs to print an object.  You might require a
String:

sub print_it ( String $thingie )
{
print $thingie;
}

Why does it have to be a String, though?  What prevents it from working
with anything that can stringify, besides the overly restrictive
signature?  What if you could say (the Perl 6 equivalent of): 

sub print_it ( does Stringify $thingie )
{
print $thingie.stringify();
}

That's both more general and something more specific.  By asking for
what you really want, you're not coding everyone else into a corner.

Take Mail::SimpleList and Mail::TempAddress, for example.  Both have
classes that represent individual addresses or mailing lists.  The
appropriate parent class is Mail::Action::Address, which has the very
basic data and properties that both subclasses share.

Both simple lists and temp addresses should contain expiration dates, so
both classes need some sort of behavior to implement that.

When you throw another class into the mix, say, Mail::OneWayList, where
there's no expiration (trust me, even though it's not on the CPAN yet),
there's a problem.

I'd like to share code between all three classes that represent aliases
and Mail::Action::Address is the appropriate place to do that.  I don't
want to share *all* of the code, though, so I can't really put the
expiration code in Mail::Action::Address.

I *could* subclass Mail::Action::Address and make
Mail::Action::Address::Expires and change the parent class of the temp
address and the simple list classes, but that's kinda icky as it leads
to yet another level in the class hierarchy.

By turning expiration into a role, though, everything can extend
Mail::Action::Address and only those classes that really need expiration
can do it -- and they share the code.

Contrived example?  Maybe.  Maybe not.  Consider further James
Fitzgibbon's Mail::Action::Role::Purge.  James wanted to extend all
Mail::Action subclasses to allow purging of expired addresses or lists. 
That's reasonable, but it's not something I wanted to add to
Mail::Action because it doesn't know anything about expiration.

So he made it a role and decorates expirable objects with the role and
can do what he wants there.

Again, the goals are specificity, genericity, and improved reuse.

-- c