but true

70 views
Skip to first unread message

Adam D. Lopresto

unread,
Dec 19, 2003, 11:36:01 AM12/19/03
to perl6-l...@perl.org
I've been trying to follow the recent discussion on roles and properties and
traits and such, but there's something that bugs me. If I understand
correctly, adding a role at runtime using but won't override any methods
defined by the class itself (but it will override inherited methods). But then
if I create a class that has its own method of saying whether it's true or not,
does that mean that "but true" and "but false" won't do anything to it?

class Complex {
has $.real;
has $.imag;

...

#Actually, how do we define this?
method asBoolean(Complex $self:){
return $self.real || $self.imag;
}


...


then somewhere in a function

return Complex::new(0,0) but true;

Since Complex already has an implementation of whatever method decides whether
it's true or not, wouldn't just applying a property be insufficient to override
that?
--
Adam Lopresto
http://cec.wustl.edu/~adam/

Where now the horse and the rider? Where is the horn that was blowing?
Where is the helm and the hauberk, and the bright hair flowing?
Where is the hand on the harpstring, and the red fire glowing?
Where is the spring and the harvest and the tall corn growing?
They have passed like rain on the mountain, like a wind in the meadow;
The days have gone down in the West behind the hills into shadow.
Who shall gather the smoke of the dead wood burning,
Or behold the flowing years from the Sea returning?

Austin Hastings

unread,
Dec 19, 2003, 12:21:23 PM12/19/03
to Adam D. Lopresto, perl6-l...@perl.org

--- "Adam D. Lopresto" <ad...@pubcrawler.org> wrote:
> I've been trying to follow the recent discussion on roles and
> properties and traits and such, but there's something that bugs me.

I tried for weeks before I could download the "traits paper". I finally
got it this week, and it has clarified some stuff (good and bad).

> If I understand correctly, adding a role at runtime using but won't
> override any methods defined by the class itself (but it will
> override inherited methods).

I think this is (or should be) false.

Traits added to a class cannot conflict (per the paper and $Larry), but
traits added at run-time would be a different category. Larry said
something about dynamic derivation of a singleton class, etc.

> But then if I create a class that has its own method of saying
> whether it's true or not, does that mean that "but true" and "but
> false" won't do anything to it?

There's the rub, eh? If you define a trait, say "Deaf", that is
intended to supercede normal behavior:

my $Grandma is NicePerson but Deaf;

then it doesn't work. That sort of runtimeness has to be allowed for
somehow.

One way, obviously, is to make run-time and compile-time separate, but
that doesn't work (see prior messages on mod-perl, etc).

Another way is declaration (class) versus dynamic composition
(per-object).

Another way (not orthogonal, btw) would be Larry's notion of declaring
what you intend to screw up.


> class Complex {
> has $.real;
> has $.imag;
>
> ...
>
> #Actually, how do we define this?
> method asBoolean(Complex $self:){
> return $self.real || $self.imag;
> }
>
>
> ...
>
>
> then somewhere in a function
>
> return Complex::new(0,0) but true;

Alternatively, think of the "simple" properties not as C<trait>
specifications, but as method overrides.

In this case, we're dynamically modifying the method table for the
object (i.e., dynamically creating a class) such that a given method
behaves the way we want:

macro true {
"&.asBoolean { return 1; }"
}

Complex::new(0,0) but true;

becomes

Complex::new(0,0) but &.asBoolean { return 1; }

(This is syntactic sugar, not a real macro, because it couldn't handle
the C<if $complex.true> form. Maybe a better macro programmer?)


> Since Complex already has an implementation of whatever method
> decides whether it's true or not, wouldn't just applying a property
> be insufficient to override that?

That would be pointless, wouldn't it?

=Austin

Larry Wall

unread,
Dec 19, 2003, 1:42:24 PM12/19/03
to perl6-l...@perl.org
On Fri, Dec 19, 2003 at 10:36:01AM -0600, Adam D. Lopresto wrote:
: I've been trying to follow the recent discussion on roles and properties and

: traits and such, but there's something that bugs me. If I understand
: correctly, adding a role at runtime using but won't override any methods
: defined by the class itself (but it will override inherited methods). But then
: if I create a class that has its own method of saying whether it's true or not,
: does that mean that "but true" and "but false" won't do anything to it?
:
: class Complex {
: has $.real;
: has $.imag;
:
: ...
:
: #Actually, how do we define this?
: method asBoolean(Complex $self:){
: return $self.real || $self.imag;
: }
:
:
: ...
:
:
: then somewhere in a function
:
: return Complex::new(0,0) but true;
:
: Since Complex already has an implementation of whatever method decides whether
: it's true or not, wouldn't just applying a property be insufficient to override
: that?

That is a problem, and you'll notice I haven't answered Jonathan Lang yet.
That's because I've been thinking about this issue all week, and I haven't
thought of a way around the problem. Which probably means that C<but>
really does imply the derivation of a new class somehow. Which in turn
implies that C<but> is probably not powerful enough yet, because it might
not only bind roles, but also new class methods to control those roles.
Maybe

$x but bar

is just shorthand for something like:

$x but class AnonClass is classof($x) does FooBar[bar] { }

(presuming that bar is an enum of type FooBar).

But it's not clear in that case how you go about caching identical
anonymous classes. Well, okay, all you have to do is memoize
the metaclass's class generator, but still...

Maybe there's an intermediate syntactic form like:

$x but subclass MyClass does FooBar[bar] { }

Or maybe the long form is just

class AnonClass is classof($x) does FooBar[bar] { }.bless($x)

except that actually putting a run-time $x into a compile-time
declaration is a bit of a problem, and it'd be nice to get rid of
the redundant $x. (Plus .bless is maybe gonna try and do things we
don't want done to $x.) On the other hand, if "bar" is some kind of
BUILD argument rather than a subtype, maybe it's

class AnonClass is classof($x) does FooBar { }.bless($x, foobar => bar)

Maybe with a lazy "isa" applied by subclass's .bless we can reduce that to:

subclass does FooBar { }.bless($x, foobar => bar)

However we write it, this derivation does do something more like a
"slatheron" with respect to the original class. However, a single
such "slather" can apply multiple roles as well as new class methods.
So all the compositional power of roles is still there within that
new class. I guess the real power of roles comes from their parallel
composition into a class, not from being able to apply them one by
one at run time. So what we need to do is make C<but> apply a new
class containing some number of collected and rationalized roles
(usually one). Call it controlled slathering...it lets you use
inheritance for slathering as it should be, while not forcing you
to use extra levels of inheritance to mix in multiple roles when
you should instead be using a composition.

I think I'm happier with that. $rubyometer += 0.3 or so. :-)

Larry

Austin Hastings

unread,
Dec 19, 2003, 1:23:45 PM12/19/03
to perl6-l...@perl.org

Going further, what's C<true>?

trait Boolean {
requires <<&.value>>;
method true {+(.value) != 0; }
method false {!?.true}
}

trait true
does Boolean
{
method true { 1; }
method false { 0; }
}

trait true
does Boolean
{
method true { 0; }
method false { 1; }
}

Then:

my $x = 0 but true;

Means
my [ class $_temp0123 is Scalar does true; ] $x = 0;

Of course, when I do:

my $x = 0 but (true|false);

then what happens?

=Austin

Larry Wall

unread,
Dec 19, 2003, 1:52:57 PM12/19/03
to perl6-l...@perl.org
On Fri, Dec 19, 2003 at 10:23:45AM -0800, Austin Hastings wrote:
: Of course, when I do:

:
: my $x = 0 but (true|false);
:
: then what happens?

That's the problem with making them methods. Any such operational
definition is going to get you in trouble. I think I like them better
as enums, because then you can have junctions of them functioning as
a kind of subtype. Of course, such a junction may well give Parrot
hissyfits at a lower level if there's a hardwired boolean bit that
Parrot is trying to set and/or unset simultaneously, but that's
perhaps a special case. I don't think we'll necessarily see such
a bit for boolean, since most built-in types define their truth in
terms of their actual value. It's quite a bit more likely that
Parrot will get heartburn from:

my $x = <$*IN> but (tainted|untainted);

That's because there's likely to be a "tainted" bit in the PMC somewhere,
since taintedness isn't a function of the data itself, but of its source.

Larry

Abhijit A. Mahabal

unread,
Dec 19, 2003, 2:10:15 PM12/19/03
to Larry Wall, perl6-l...@perl.org
On Fri, 19 Dec 2003, Larry Wall wrote:

> On Fri, Dec 19, 2003 at 10:23:45AM -0800, Austin Hastings wrote:
> : Of course, when I do:
> :
> : my $x = 0 but (true|false);
> :
> : then what happens?
>
> That's the problem with making them methods. Any such operational
> definition is going to get you in trouble. I think I like them better
> as enums, because then you can have junctions of them functioning as
> a kind of subtype.

Is that thought about just traits, or also about roles? Sometime earlier
Larry mentioned that roles could add multimethods, and my worry about that
is this:
If you simultaneously have a multi method with a signature and
another without, given a particular call to this multimethod how do you
choose which of the two happens if the signature matches? Disallowing such
clashes seems problematic because it may mean that if the class writer
used types and signatures these get forced onto the user of the class.

--Abhijit

Luke Palmer

unread,
Dec 19, 2003, 2:24:29 PM12/19/03
to Abhijit A. Mahabal, Larry Wall, perl6-l...@perl.org
Abhijit A. Mahabal writes:
> On Fri, 19 Dec 2003, Larry Wall wrote:
>
> > On Fri, Dec 19, 2003 at 10:23:45AM -0800, Austin Hastings wrote:
> > : Of course, when I do:
> > :
> > : my $x = 0 but (true|false);
> > :
> > : then what happens?
> >
> > That's the problem with making them methods. Any such operational
> > definition is going to get you in trouble. I think I like them better
> > as enums, because then you can have junctions of them functioning as
> > a kind of subtype.
>
> Is that thought about just traits, or also about roles?

Neither. It's just about roles. We're having another vocabulary
conflict; refer to the vocabulary doc.

> Sometime earlier Larry mentioned that roles could add multimethods,
> and my worry about that is this:
> If you simultaneously have a multi method with a signature and
> another without, given a particular call to this multimethod how do you
> choose which of the two happens if the signature matches?

Probably the same way you disambiguate when normal multimethods abound.
The more specific signature wins, if it matches.

Though I do see how this might introduce subtle bugs. I'm a big fan of
method name-only equivalence, so I would argue that it overrides (or
subsides if it isn't being slathered on), but then I don't have
experience with large-scale projects.

> Disallowing such clashes seems problematic because it may mean that if
> the class writer used types and signatures these get forced onto the
> user of the class.

Everybody's going to be using signatures, though! (Types are a
different story) Yeah, the typeless one would win, I think, unless the
type happens to be Any.

Luke

Larry Wall

unread,
Dec 19, 2003, 3:25:51 PM12/19/03
to perl6-l...@perl.org
On Fri, Dec 19, 2003 at 12:24:29PM -0700, Luke Palmer wrote:
: Abhijit A. Mahabal writes:
: > On Fri, 19 Dec 2003, Larry Wall wrote:
: >
: > > On Fri, Dec 19, 2003 at 10:23:45AM -0800, Austin Hastings wrote:
: > > : Of course, when I do:
: > > :
: > > : my $x = 0 but (true|false);
: > > :
: > > : then what happens?
: > >
: > > That's the problem with making them methods. Any such operational
: > > definition is going to get you in trouble. I think I like them better
: > > as enums, because then you can have junctions of them functioning as
: > > a kind of subtype.
: >
: > Is that thought about just traits, or also about roles?
:
: Neither. It's just about roles. We're having another vocabulary
: conflict; refer to the vocabulary doc.

I've been trying to capitalize Traits when I'm referring back the Traits
paper, and keeping it lowercase when I mean Perl 6 compile-time traits.
Sometimes it means I have to recast the sentence not to say "traits"
at the beginning though...

: > Sometime earlier Larry mentioned that roles could add multimethods,


: > and my worry about that is this:
: > If you simultaneously have a multi method with a signature and
: > another without, given a particular call to this multimethod how do you
: > choose which of the two happens if the signature matches?
:
: Probably the same way you disambiguate when normal multimethods abound.
: The more specific signature wins, if it matches.

A crude distance calculation is done in typespace for all the involved
parameters. It is sufficiently crude that ties can arise when we *ought*
to be uncertain which method to call. In that case we'll have some
way of declaring how to break the tie. If the tie can't be broken,
and exception is then thrown.

: Though I do see how this might introduce subtle bugs. I'm a big fan of


: method name-only equivalence, so I would argue that it overrides (or
: subsides if it isn't being slathered on), but then I don't have
: experience with large-scale projects.

These multis are intra-class multis. Outside the class, the method has
only a single name. With ordinary method dispatch, you figure out which
name in which class you're going to call, and only then do you notice
that there are more than one of them within the class. These are
"multi methods", not "multimethods" in the classic sense. For classic
multimethods you have to declare multiple instances of "multi sub *foo"
and call it/them as a subroutine (or operator). But we've generalized
"multi" to work in any namespace that would ordinarily reject a duplicate
definition.

: > Disallowing such clashes seems problematic because it may mean that if


: > the class writer used types and signatures these get forced onto the
: > user of the class.

Not necessarily. Remember that multi dispatch is based on run-time
types, not declared types. A module could be totally ignorant of
the run-time types of its values and it would still work, as long as
whatever produced the values in the first place labelled them with
the right type. And you have to call the right constructor in the
first place to get the right values, even if you subsequently store
everything in typeless variables, so nothing is really forced on the
user that wasn't implicitly there to begin with.

: Everybody's going to be using signatures, though! (Types are a


: different story) Yeah, the typeless one would win, I think, unless the
: type happens to be Any.

Not sure what you mean. The typeless one is likely to "lose" in the
sense that it's probably the furthest away in type space. But by the
same token, it's likely to be the one that should be default in case of
ties, unless one of the tied entrants is specially marked as "better".
But it's hard to know how much tie-breaking information you want to
throw into the declarations, since you generally want to call the
most specific entrant that will successfully handle the arguments, and
"most specific" is a function of type distance, not which entrant yells
the loudest about its own superiority. So maybe the better solution
is to allow class derivations to specify their type distance if it's
other than 1, just as IP routing tables can have a notion of which
hops are expensive and which ones are cheap. It's probably better
to attach such information to the class rather than splattering it
all over multi-dom. As with IP routing, mostly it's the "expensive"
routes that are specifically marked, and everything else defaults to 1.
A derivation that redefines most of the base class's methods should
probably be marked as an "expensive route". (Such derivation distance
could be automatically calculated, but then our mechanism is never
crude enough to get ties when we probably should.)

Larry

Jonathan Lang

unread,
Dec 20, 2003, 5:02:11 PM12/20/03
to Larry Wall, perl6-l...@perl.org
Larry Wall wrote:
> Maybe there's an intermediate syntactic form like:
>
> $x but subclass MyClass does FooBar[bar] { }

IMHO, C<but> should be defined as generating a singleton class that
derives from the variable's class and composes a specified role - but not
neccessarily a I<pre-existing> role. How about defining it such that the
presence of C<is>, C<does>, or curly braces immediately following C<but>
implies that the term is an anonymous role definition:

$x but is red does bar { }

eqv

role AnonRole is red does bar { }
$x but AnonRole;

eqv

role AnonRole is red does FooBar[bar] { }
$x but AnonRole;

You never slatheron more than one role at a time; but you can create the
role that you're going to slatheron on the fly. Potential problem:
identifying duplicate anonymous roles (an issue of optimization). The
upside: once that problem's solved, the problem of caching singleton
classes is greatly simplified. Also, it removes the run-time $x from the
compile-time side of things.

There's one "degenerate case" for on-the-fly roles:

$x but does foo { }

eqv

$x but foo;

=====
Jonathan "Dataweaver" Lang

__________________________________
Do you Yahoo!?
New Yahoo! Photos - easier uploading and sharing.
http://photos.yahoo.com/

Simon Cozens

unread,
Dec 20, 2003, 5:23:54 PM12/20/03
to perl6-l...@perl.org
la...@wall.org (Larry Wall) writes:
> is classof($x)

Ouch. $x's class isn't a property or trait of it?

> class AnonClass is classof($x) does FooBar { }.bless($x, foobar => bar)

I don't understand what the bit at the end is doing. This is calling .bless
on the overriden method? And I'm not sure I follow the 'foobar => bar'.

> I think I'm happier with that. $rubyometer += 0.3 or so. :-)

Except it loses about 5 points for that classof thing. ;)

--
As in certain cults it is possible to kill a process if you know its true name.
-- Ken Thompson and Dennis M. Ritchie

Piers Cawley

unread,
Dec 23, 2003, 2:46:56 PM12/23/03
to perl6-l...@perl.org
Larry Wall <la...@wall.org> writes:
> On Fri, Dec 19, 2003 at 10:36:01AM -0600, Adam D. Lopresto wrote:
> : I've been trying to follow the recent discussion on roles and
> : properties and traits and such, but there's something that bugs
> : me. If I understand correctly, adding a role at runtime using but
> : won't override any methods defined by the class itself (but it
> : will override inherited methods). But then if I create a class
> : that has its own method of saying whether it's true or not, does
> : that mean that "but true" and "but false" won't do anything to it?
> :
> : class Complex {
> : has $.real;
> : has $.imag;
> :

[...]

> : Since Complex already has an implementation of whatever method decides whether
> : it's true or not, wouldn't just applying a property be insufficient to override
> : that?
>
> That is a problem, and you'll notice I haven't answered Jonathan
> Lang yet. That's because I've been thinking about this issue all
> week, and I haven't thought of a way around the problem. Which
> probably means that C<but> really does imply the derivation of a new
> class somehow. Which in turn implies that C<but> is probably not
> powerful enough yet, because it might not only bind roles, but also
> new class methods to control those roles. Maybe

[...]

> However we write it, this derivation does do something more like a
> "slatheron" with respect to the original class. However, a single
> such "slather" can apply multiple roles as well as new class methods.
> So all the compositional power of roles is still there within that
> new class. I guess the real power of roles comes from their parallel
> composition into a class, not from being able to apply them one by
> one at run time. So what we need to do is make C<but> apply a new
> class containing some number of collected and rationalized roles
> (usually one). Call it controlled slathering...it lets you use
> inheritance for slathering as it should be, while not forcing you
> to use extra levels of inheritance to mix in multiple roles when
> you should instead be using a composition.

Will this approach allow for the removal of a property? (I'm currently
stuck for a suggested syntax...)

--
Beware the Perl 6 early morning joggers -- Allison Randal

Larry Wall

unread,
Dec 23, 2003, 8:33:26 PM12/23/03
to perl6-l...@perl.org
On Tue, Dec 23, 2003 at 07:46:56PM +0000, Piers Cawley wrote:
: Will this approach allow for the removal of a property? (I'm currently

: stuck for a suggested syntax...)

If a property is an enumified sort of role, then in general you don't
disable a property by removing it, but by setting the value to the enum
value that means "nope". For example, there isn't a "true" property,
per se. There's a Boolean role/property with a boolean attribute that
can have the value either true or false. When you say "but true",
it first makes sure that your object "does Boolean", and then it
calls the corresponding boolean accessor to set the value to true.

Now, maybe some roles can be self-removing, if you set them to
a particular default value, or twiddle their interface some way.
But the general way to cut down the capabilities of a type is to
subtype it. So removal of a role might fall out of some kind of
syntax that does a force-to-subtype operation, if we support such
an operation. Can't be more specific than that right now.

Larry

Reply all
Reply to author
Forward
0 new messages