Roles as anonymous and/or closures

5 views
Skip to first unread message

Aaron Sherman

unread,
Apr 26, 2005, 9:25:45 AM4/26/05
to Perl6 Language List
Is any of this legal?

class car {
...
method make ($self: $make, *@models) returns(car) {
return $self but role {
has $.make = $make;
method model($self: $model) returns(car) {
unless $model eq any(@models) {
die "Invalid model: $model";
}
return $self but role {
has $.model = $model;
}
}
}
}
}
my car $generic .= new;
my car $ford = $generic.make("ford",<pinto mustang>);
my car $pinto = $ford.model("pinto");

It certainly seems very attractive, but I'm not sure if roles can be
anonymous and/or closures.

If we can do this, then it brings up the possibility of currying
mixin-generator methods and all sorts of other useful features which
would greatly simplify some very complex classes.

It also might be useful for roles to be able to delete members and
methods from a class like so:

role foo {
has $.x;
has not $.y;
}

This allows a role to "reset" the application of subordinate roles (as
the example method, make, might want to reset the application of its own
"model" method's anon role).

"has not" precludes ever having a type named "not", and if that's a
problem it could read "not has" or "!has", but that feels a bit klunkier
to me.

--
Aaron Sherman <a...@ajs.com>
Senior Systems Engineer and Toolsmith
"It's the sound of a satellite saying, 'get me down!'" -Shriekback


Abhijit Mahabal

unread,
Apr 26, 2005, 9:58:03 AM4/26/05
to Aaron Sherman, Perl6 Language List
On Tue, 26 Apr 2005, Aaron Sherman wrote:

> It also might be useful for roles to be able to delete members and
> methods from a class like so:
>
> role foo {
> has $.x;
> has not $.y;
> }

But that brings up the issue of who has the final authority. In class
composition, a method defined in the class hides those in the roles, and
in this sense it is the boss on "adding decisions". I like this a lot
because I think it makes it possible for me to read a class description
and have a sense of what is going on. With the "has not" proposal, it
seems that the role would need to be the boss on "deleting decisions".
Could get pretty confusing!

--abhijit

Abhijit Mahabal http://www.cs.indiana.edu/~amahabal/

Juerd

unread,
Apr 26, 2005, 9:49:50 AM4/26/05
to Aaron Sherman, Perl6 Language List
All IIRC/AFAIK:

Aaron Sherman skribis 2005-04-26 9:25 (-0400):


> method make ($self: $make, *@models) returns(car) {

returns car;

(And write classes ucfirst, please)

> return $self but role {

does role { ... }

> It certainly seems very attractive, but I'm not sure if roles can be
> anonymous and/or closures.

They can. But I think what you wrote is rather unnecessarily complex.


Juerd
--
http://convolution.nl/maak_juerd_blij.html
http://convolution.nl/make_juerd_happy.html
http://convolution.nl/gajigu_juerd_n.html

Aaron Sherman

unread,
Apr 26, 2005, 10:03:30 AM4/26/05
to Juerd, Perl6 Language List
On Tue, 2005-04-26 at 09:49, Juerd wrote:

> > return $self but role {
>
> does role { ... }

As I understood (please correct me if I'm wrong), the difference between
"does" and "but" was that does modifies the existing object in-place,
and does creates a copy with the new mixin functionality. In this case,
the method in question is acting as a generator, and should NOT modify
the invocant.

I'm getting this from S12:


Then you can say

$a = 0 but answer(42)

Note that the parenthesized form is not a subroutine or method
call. It's just special initializing syntax for roles that
contain a single property. The above really means something
like:

$a = ($anonymous = 0) does answer(42);

which really means:

(($anonymous = 0) does answer).answer = 42;
$a = $anonymous;

Which is why there's a but operator.

> > It certainly seems very attractive, but I'm not sure if roles can be
> > anonymous and/or closures.
>
> They can. But I think what you wrote is rather unnecessarily complex.

How is this complex? This is fairly standard for a factory type method
(I think I said "generator" before, oops), but in most languages, a
factory either has to return from a pre-defined tree of classes, or has
to build its own mechanism. In Perl 6, closures combined with anonymous
roles let us build this functionality trivially, on the fly.

Aaron Sherman

unread,
Apr 26, 2005, 10:49:32 AM4/26/05
to Abhijit Mahabal, Perl6 Language List
On Tue, 2005-04-26 at 09:58, Abhijit Mahabal wrote:
> On Tue, 26 Apr 2005, Aaron Sherman wrote:
>
> > It also might be useful for roles to be able to delete members and
> > methods from a class like so:
> >
> > role foo {
> > has $.x;
> > has not $.y;
> > }
>
> But that brings up the issue of who has the final authority. In class
> composition, a method defined in the class hides those in the roles, and
> in this sense it is the boss on "adding decisions".

Quoting S12:

A class's method definition hides any role definition of the
same name, so role methods are second-class citizens. On the
other hand, role methods are still part of the class itself, so
they hide any methods inherited from other classes, which makes
ordinary inherited methods third-class citizens, as it were.

So in the case of class construction:

class x is y does z {...}

you should get x's methods plus any new ones from z plus any new ones
from y.

In the case of a mixin, I THINK the actual type of the new value is an
anonymous class, so it's something like this:

my $x = $y but z;

is

my (class {is ::{$y};does z;} $x = $y.clone;

or whatever the copy syntax is (and I might be wrong about how to
specify the type of $y... is there a typeof()?)

So, as you can see, in the case of mixins, the hypothetical:

role z {
has not mymeth;
}

would, in fact, remove mymeth from $x, and in class composition, it
would remove the method from parents, but not from the class being
declared (as it should not, by my way of thinking).

Aaron Sherman

unread,
Apr 26, 2005, 10:53:55 AM4/26/05
to Perl6 Language List
On Tue, 2005-04-26 at 10:49, Aaron Sherman wrote:

> Quoting S12:
>
> A class's method definition hides any role definition of the
> same name, so role methods are second-class citizens. On the
> other hand, role methods are still part of the class itself, so
> they hide any methods inherited from other classes, which makes
> ordinary inherited methods third-class citizens, as it were.

Oops, I was quoting A12, not S12. S12 says:

A class's explicit method definition hides any role definition
of the same name. A role method in turn hides any methods
inherited from other classes.

which is pretty much the same thing.

Abhijit Mahabal

unread,
Apr 26, 2005, 12:44:12 PM4/26/05
to Perl6 Language List
On Tue, 26 Apr 2005, Aaron Sherman wrote:

> On Tue, 2005-04-26 at 09:58, Abhijit Mahabal wrote:
>> On Tue, 26 Apr 2005, Aaron Sherman wrote:
>>
>>> It also might be useful for roles to be able to delete members and
>>> methods from a class like so:
>>>
>>> role foo {
>>> has $.x;
>>> has not $.y;
>>> }
>>
>> But that brings up the issue of who has the final authority. In class
>> composition, a method defined in the class hides those in the roles, and
>> in this sense it is the boss on "adding decisions".
>

> So, as you can see, in the case of mixins, the hypothetical:
>
> role z {
> has not mymeth;
> }
>
> would, in fact, remove mymeth from $x, and in class composition, it
> would remove the method from parents, but not from the class being
> declared (as it should not, by my way of thinking).

Assuming that mymeth isn't AUTOMETHed, isn't that equivalent to saying:

role z{
method mymeth(*@_) {...}
}

Moreover, how does 'has not' work with multis? Does it clobber multi's
of all signatures? what if you have something like:

class A { multi method foo($x){ something } }
role B { has not foo; has not die;}
class C is A does B {...}

# the theft of ... for real code does make writing pseudocode harder!


I am just thinking aloud. I do like the proposal at least somewhat, and
was wondering if it could be used as an aid in refactoring: an easy way to
comment out methods to see if we have forgotten to change a call
somewhere.

Aaron Sherman

unread,
Apr 26, 2005, 1:00:17 PM4/26/05
to Abhijit Mahabal, Perl6 Language List
On Tue, 2005-04-26 at 12:44, Abhijit Mahabal wrote:
> On Tue, 26 Apr 2005, Aaron Sherman wrote:

> > So, as you can see, in the case of mixins, the hypothetical:
> >
> > role z {
> > has not mymeth;
> > }

Sorry, my bad. I wandered sideways into talking about methods. "has", of
course, only introduces MEMBERS. It's been kinda rough switching to
getting up early ;-)

"has not $.foo" seems useful to me, but I think there are other, more
useful ways to deal with methods.

> I am just thinking aloud. I do like the proposal at least somewhat, and
> was wondering if it could be used as an aid in refactoring: an easy way to
> comment out methods to see if we have forgotten to change a call
> somewhere.

For methods, yes, it would be a nice way to do that sort of thing, but I
would think it would be more like what you suggested there:

method mymeth(*@){...}

Though, that might not be perfect in some cases, where you want:

exists &{class.mymeth}

to say false.

Luke Palmer

unread,
Apr 26, 2005, 11:19:04 AM4/26/05
to Juerd, Aaron Sherman, Perl6 Language List
Juerd writes:
> (And write classes ucfirst, please)
>
> > return $self but role {
>
> does role { ... }

Nope, Aaron was right here, since you're not trying to mutate $self;
you're just trying to return a new $self with other capabilities.

> > It certainly seems very attractive, but I'm not sure if roles can be
> > anonymous and/or closures.
>
> They can. But I think what you wrote is rather unnecessarily complex.

Perhaps for this case, but I could see situations where this technique
could be valuable.

Luke

Reply all
Reply to author
Forward
0 new messages