For example, it may want to ensure that the class has $.foo. (*)
I have a few questions:
1: Can this be achieved by a CHECK {} block in the role, that gets run
just before the class composition is over? Or should it be spelled
differently, CHECK {} being the last thing that run before "run-time"?
2: What is the syntax for checking that a class has a variable? In this
case the class does not even really exist when we want to check.
3: If arbitrary things can go into such a CHECK{} block, then the
following two may not mean the same:
does A does B;
does B does A;
Are roles I<expected> to play nice, or I<forced> to play nice?
--abhijit
(*) The solution "add a C<has $.foo> to the role itself, and if the class
has a $.foo, it takes precedence" does not work because $.foo may have
been added by another role.
Abhijit Mahabal http://www.cs.indiana.edu/~amahabal/
Let me start by pointing out a bit of abstraction sacreligion here, and
responding to your second question.
Neither a class nor an object can have $.foo. They have .foo, the
accessor, and only the methods have $.foo. I don't believe roles can
see the $.foo, so they also have to use .foo.
But as far as I can tell, this has little to do with the main point of
your question.
> I have a few questions:
>
> 1: Can this be achieved by a CHECK {} block in the role, that gets run
> just before the class composition is over? Or should it be spelled
> differently, CHECK {} being the last thing that run before "run-time"?
I'd say something like that. Perhaps it's a COMPOSE submethod, that
ironically doesn't get composed, because it's special that way. I don't
like that much, because it breaks the generality of composition.
Perhaps just:
multi sub does (::class, MyRole $role) {...}
Which would be run instead of the default does, but you could easily
call the default does at the top of that and then do some checking at
the bottom.
Luke
> 2: What is the syntax for checking that a class has a variable? In this
> case the class does not even really exist when we want to check.
This is somewhat bogus, as I pointed out above, but if you're feeling
really naughty, you can do it:
$obj.HAS.exists('$.foo');
Or:
SomeClass.HAS.exists('$.foo');
> 3: If arbitrary things can go into such a CHECK{} block, then the
> following two may not mean the same:
> does A does B;
> does B does A;
> Are roles I<expected> to play nice, or I<forced> to play nice?
Perl doesn't force anything, but you can consider it a strong
expectation.
Luke
> Abhijit Mahabal writes:
>
> But as far as I can tell, this has little to do with the main point of
> your question.
Yes. I would be happy enough checking the existence of a .foo accessor.
>
> > I have a few questions:
> >
> > 1: Can this be achieved by a CHECK {} block in the role, that gets run
> > just before the class composition is over? Or should it be spelled
> > differently, CHECK {} being the last thing that run before "run-time"?
>
> I'd say something like that. Perhaps it's a COMPOSE submethod, that
> ironically doesn't get composed, because it's special that way. I don't
> like that much, because it breaks the generality of composition.
> Perhaps just:
>
> multi sub does (::class, MyRole $role) {...}
>
> Which would be run instead of the default does, but you could easily
> call the default does at the top of that and then do some checking at
> the bottom.
>
But that would not solve my problem. Consider the following scenario:
Role Pet { has $.tail; ... }
Role TailStuff {
method wagtail { loop {.tail.move_down; .tail.move_up; } }
COMPOSE {...}
}
Class Animal does TailStuff does Pet { ... }
What I want TailStuff to be able to do is do a sanity check by ensuring
that the composed class has a .tail. When TailStuff's COMPOSE method is
called, it is too early to check for .tail; This check will have to happen
after all the COMPOSE{...} of all the roles has been done. My example is
not good in that one can say "just refactor your roles", but there could
be real cases where you do not want to declare a method, but want to have
it anyway.
> > 3: If arbitrary things can go into such a CHECK{} block, then the
> > following two may not mean the same:
> > does A does B;
> > does B does A;
> > Are roles I<expected> to play nice, or I<forced> to play nice?
>
> Perl doesn't force anything, but you can consider it a strong
> expectation.
Sure, but in this case I thought forcing wasn't necessarily bad as there
are traits anyway. And it'd be a good idea if I can trust that the order
of composition of roles is immaterial, Unless, of course, the cultural or
usability costs are too high.
-abhijit
What kind of alien wagging is this? Every dog I've known wags its
tail from side to side. :-)
> COMPOSE {...}
> }
> Class Animal does TailStuff does Pet { ... }
>
> What I want TailStuff to be able to do is do a sanity check by ensuring
> that the composed class has a .tail.
If your TailStuff role requires a $.tail, just include it in your
role. Or if you have a really good reason for separating the tail
from the actions that apply to it, couldn't you do something like
this:
role Pet { has $.tail; ... }
role TailStuff does Pet { ... }
?
> When TailStuff's COMPOSE method is
> called, it is too early to check for .tail; This check will have to happen
> after all the COMPOSE{...} of all the roles has been done. My example is
> not good in that one can say "just refactor your roles", but there could
> be real cases where you do not want to declare a method, but want to have
> it anyway.
I'm suffering a failure of imagination here I think.
-Scott
--
Jonathan Scott Duff
du...@pobox.com
Another example to clarify what I am getting at:
Role Log2File [: $filename] { method do_the_logging {...}; ... }
Role Log2Email [: $address ] { method do_the_logging {...}; ... }
Role Log2Tk [: $widget ] { method do_the_logging {...}; ... }
Role SimpleLog {
method log( $msg ) { .do_the_logging( $msg ) }
}
Role PoeticLog {
my sub make_into_poem {...}
method log( $msg ) {
.do_the_logging( make_into_a_poem( $msg ) );
}
}
Class Poem does PoeticLog does Log2Email[f...@bar.com] {...}
>
> > COMPOSE {...}
> > }
> > Class Animal does TailStuff does Pet { ... }
> >
> > What I want TailStuff to be able to do is do a sanity check by ensuring
> > that the composed class has a .tail.
>
> If your TailStuff role requires a $.tail, just include it in your
> role.
Can't do that. Will clash with Log2Email's $.tail, er, .do_the_logging
> Or if you have a really good reason for separating the tail
> from the actions that apply to it, couldn't you do something like
> this:
>
> role Pet { has $.tail; ... }
> role TailStuff does Pet { ... }
Can't do that either; Don't know which of the many Pets will provide
.do_the_logging
>
> > When TailStuff's COMPOSE method is
> > called, it is too early to check for .tail; This check will have to happen
> > after all the COMPOSE{...} of all the roles has been done. My example is
> > not good in that one can say "just refactor your roles", but there could
> > be real cases where you do not want to declare a method, but want to have
> > it anyway.
>
> I'm suffering a failure of imagination here I think.
Er, I should have said "define a method" rather than "declare a method".
Sorry.
In the example above, PoeticLog does not want to define the method
.do_the_logging, but needs it to have been defined by somebody anyway.
To reiterate my question with this new example, "Can PoeticLog somehow
ensure that somebody has defined .do_the_logging?"
Even if PoeticLog is unable to do the checking, the problem will still be
caught at runtime, of course.
--abhijit
It's his pet whale.
Pm
[ deletia ]
> In the example above, PoeticLog does not want to define the method
> .do_the_logging, but needs it to have been defined by somebody anyway.
>
> To reiterate my question with this new example, "Can PoeticLog somehow
> ensure that somebody has defined .do_the_logging?"
Hmm. So you want to check immediately after class/object composition
time that the class/object has a do_the_logging routine?
I didn't see any mention of this in a quick search through the
Apocalypses, but surely you can apply PRE and POST to roles. I.e.
role PoeticLog {
...
POST { exists &do_the_logging }
}
would "fire" at class/object composition time. (PRE would fire just
before composition, POST immediately after). I seem to recall
something like this for classes too (though I may have imagined it)
where PRE blocks would fire immediately upon instantiation, and POST
blocks immediately after instantiation. Er, perhaps the terminology
is wacky there. The instantiation process goes PRE,BUILD,POST and
doesn't actually happen unless all of those happen.