in reply to Class::Trait to the CPAN?

Have you ever used traits in any language?
Nope.
Would you use a traits implementation in Perl?
Depends upon who good it was :)
How would you improve the interface above?

To start with I would not use the Trait::* namespace in the way you are. It is making assumptions that my application does not have another need for that namespace. I see what you are trying to do with it, and I recomend that you make all trait's inherit from a base Trait class instead.

I would also combine the 2 use statements into one, so that:

use Class::Trait 'LifeGuard'; use Class::Trait 'Dog' => { explicit => 'swim' };
would turn into :
use Class::Trait ( 'Trait::LifeGuard', 'Trait::Dog' => { explicit => 'swim' } );
Your Class::Trait::import() code would just need to look-ahead after every trait name it found to see if there is a hash-ref to process. Pretty simple.

If all your trait classes inherit from a Trait base, further compile time checking can be done too. You can basically check that each trait being imported is a valid Trait object and is actually implemented (i.e. - exists in the symbol table).

I would also get rid of all this:

Class::Trait->promise('doggie_treat'); Class::Trait->assemble; # this flattens the traits into this class sub AUTOLOAD {  # we'll make &doggie_treat, if needed }
The promise should be auto-checked at compile-time when you load Trait::Dog with the use statement. Basically you get the list of promises for each Trait and then make sure they exist in (at a minimum) the symbol table class importing said Trait. This would allow you to use AUTOLOAD as you did above by just adding sub doggie_treat; somewhere, but I would discourage the use of AUTOLOAD because IMO it weakens the promise.

As traits are added, promises made and expectations listed, I build a composite interface (similar to a Java interface). When Class::Trait->assemble (should I call that 'flatten'?) is called, the interface is validated and conflicts are resolved.

I am not sure what you are actually doing by this description, but IMO the act of "assembling" the code (or "flattening" as the paper refers to it), should be done also at compile time. So that by the time you would reach the CHECK stage of perl compilation cycle all your traits methods should be attached and promises checked (not just made) and in general you should have a trait-object which would incur little if any additional run-time cost.

This means that I think you should alias all your trait methods to be members of the class that is using them (this is how they describe the implementation in paper). Just a simple construct like this would do:

*{"${using_pkg}::$trait_method_name"} = \&{"${trait_pkg}::$trait_metho +d_name"}
Ideally the fact your class uses traits, would never be known by any other class or module that it might encounter. This may be an idealistic POV, but its something to strive for :).

Taking all these things into account your examples would look like this:

package Person; use Class::Trait ( 'Trait::LifeGuard', 'Trait::Dog' => { explicit => 'swim' } ); sub doggie_treat { my ($self) = @_; return "Snausages,.. yummmm"; } 1;
The new (slightly expanded) traits look like this:
package Trait::LifeGuard; # make it inherit from some # kind of base Trait object use base 'Class::Trait::TraitBase'; sub swim { my ($self, $target) = @_; # would probably want to pass on any # arguments here return Trait::LifeGuard::_swim($self, $target); } # i am fleshing this out a bit to show # how if $self->swim was actually # the Trait::Dog implementation it # would still work sub save_drowning_swimmer { my ($self, $swimmer) = @_; my $shore = $self->station()->location(); $self->swim($swimmer->location()); $self->grab($swimmer); $self->swim($shore); } # i used these two methods, so lets # define them here anyway sub grab {} sub station {} 1; package Trait::Dog; # make it inherit from some # kind of base Trait object use base 'Class::Trait::TraitBase'; # make this into a variable of some # kind, kind of like @EXPORT maybe? my @EXPECTS = ('doggie_treat'); sub swim { my ($self, $target) = @_; # since we know that the 'swim' method is now # a valid method in our $self object, we can call # 'doggie_treat' on $self with confidence since all # this will have been checked at compile time Trait::Dog::_eat($self->doggie_treat()); # swim to $target # passing on any arguments here # that might be nessecary ... Trait::Dog::_swim($self, $target); } sub _eat { # this must be called via a fully qualified name because private # methods are not flattened into the primary class } 1;
Probably your best bet as to an example/test would be to try and built the 'Shape' example found in the traits paper itself. They explain it is great detail and you can use that as a bar to hold your implementation against. You may want to pick up a Smalltalk book if you really want to understand what they are doing there too.

-stvn