`I'd like to see a way to map methods and variables expected by a`

`role, onto`

methods and variables provided by a class. I'd like it to be possible for a class to provide several such maps, having the appropriate one selected according to context.

## Advertising

`Continuing an example from an earlier thread <http://`

`www.nntp.perl.org/group/perl.perl6.language/23909>,`

you might want: class RealNumber does Group; but it might do it through addition or multiplication (where zero is exceptional in the multiplication provision for the role). Then, as in Luke's example, you'd want a subroutine "power", dispatched by the role Group

`power(4, 3) # computes 4 to the third power, with respect to group`

`operation`

`to return 64 in a multiplication Group context, but 12 in an addition`

`one.`

Here's a fairly simple proposal to make this work, with three changes to the language: 1. Every class and instance would have a special hash attribute: %.?HOW is rw to be keyed on role names, and to be given method values, including "undef". These values would be dynamically scoped; an assignment to &.?HOW{$role} would implicitly carry "temp." So, you can set the %.?HOW context to something appropriate, either for a particular variable or the whole class, right before you call a sub that requires you to pick which way you're going to fill the role. (The class attribute needs a different name, maybe %.?USUALLY, since class and instance attributes share a namespace.) 2. Anywhere something is expanded to: ::T <= Role{::T} the ::T will no longer represent a Class, but a pair (Class, Method), with "undef" allowed for the method.

`So, you can't put a real number locally bound to '+' and one bound to`

`'*'`

together in a context that requires objects that all come from the same group. 3. A new keyword "through" would be added to the "does" syntax. When you say: class RealNumbers { does Group through &.times; does Group through &.plus; } you're saying that the pairs ::T = (RealNumber, &.times) and ::T = (RealNumber, &.plus) satisfy the constraint Group{::T}. If you say "does" without the "through" keyword, you're telling the dispatcher that (RealNumber, undef) satisfies the constraint. When a subroutine is to be dispatched by a role Bar, and an instance $x of class Foo, where Foo does Bar (possibly several ways), is provided, the dispatcher looks up the instance value &x.?HOW{Bar}. If it's undef, it looks at the class value &Foo::?HOW{Bar}. The method &.?HOW{Bar} is invoked on $x prior to entry into the routine. (If the instance and class values of &.?HOW{Bar} are both undef, then it just plunges in, so anything you could write before, still works after this language change.) So I could write: role Group { # requires:

`method compose (::?CLASS $operand) { ... } # product of`

`$self and $operand`

method inverse () { ... } # invert $self has $.identity; } sub power (Group $element, Int $pow) { given $pow { when $_ < 0 { power(inverse($x), -$pow) } when $_ == 0 { $.identity } when $_ > 0 { compose($x, power($x, $pow - 1)) } } } class Integer {

`does Group; # okay, just define power, identity, and compose`

`inside`

} and yet class RealNumber { has num $.x; method infix:<+>(RealNumber $y) { $.x + $y.x } method infix:<*>(RealNumber $y) { $.x * $y.x } ... method inverse (:$op) { given($op) { when '+' { 0 - $.x } when '*' { 1/ $.x } } } has $.identity; method plus() { temp &.compose = &.infix:<+>; temp &.inverse = &.inverse.assuming(:op('+')); temp $.identity = 0; } method times(); # similar does Group through &.plus; does Group through &.times; } my RealNumber ($a, $b); &.?HOW{'Group'} = &.plus for ($a, $b); ($a, $b) = (4, 3); my $c = power($a, $b); say $c; # 12 The alternative to the routines "plus" and "times" would be to make all of RealNumber's Group role routines read the %.?HOW hash individually. That would seem to work without any language modifications whatsoever, but: 1. It would put ugly case-checking in too many places, IMHO. 2. Uses of conflicting role providers wouldn't be detected. 3. If you're importing someone else's class, and the class's author didn't know about the role but you do, then you should be able to say "Pigs really can fly, and this subroutine says how they do it" without rewriting all the class method definitions. Christopher