Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss
Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

Private contracts?

6 views
Skip to first unread message

Michael G Schwern

unread,
Oct 3, 2002, 2:46:38 PM10/3/02
to perl6-l...@perl.org
I've been mucking about a bit more with this whole interface thing.

So if we make method signatures only enforced on subclasses if the parent
class or method has the interface property...

....except private methods, obviously.

And if we make pre/post conditions and class invariants always enforced...

....shouldn't we have private invariants and conditions?


class Car is interface {
attr wheels;
invar { .wheels == 4 }

method accel($how_fast);
method turn($direction, $how_sharp);
}

class ATV is Car, interface {
attr _tilt is private;
invar { ._tilt <= 20 } is private;

method turn($direction, $how_sharp) {
pre { $how_sharp <= 20 } is private;
...implementation...
}
}

I've implemented an ATV where I've put in a saftey protection against
rolling over in a turn as both an invariant and a pre-condition. It will
not allow you to turn the car too sharply, else it simply blows up. Wait
second... ;)

But I don't want my subclasses to be constrained by that. It's just an
implementation detail that I only wish to enforce upon ATV and not it's
children. So they're private.

Makes sense, no?


--

Michael G. Schwern <sch...@pobox.com> http://www.pobox.com/~schwern/
Perl Quality Assurance <per...@perl.org> Kwalitee Is Job One
Remember, any tool can be the right tool.
-- Red Green

Michael G Schwern

unread,
Oct 3, 2002, 3:00:21 PM10/3/02
to perl6-l...@perl.org
On Thu, Oct 03, 2002 at 02:46:38PM -0400, Michael G Schwern wrote:
> class ATV is Car, interface {

Hmmm. That should probably be

class ATV isa Car is interface {


--

Michael G. Schwern <sch...@pobox.com> http://www.pobox.com/~schwern/
Perl Quality Assurance <per...@perl.org> Kwalitee Is Job One

Help, help! A Heffalump, a Horrible Heffalump! Help, help, a Herrible
Hoffalump! Hoff, Hoff, a Hellible Horralump!

Allison Randal

unread,
Oct 3, 2002, 4:11:34 PM10/3/02
to perl6-l...@perl.org
On Thu, Oct 03, 2002 at 02:46:38PM -0400, Michael G Schwern wrote:
>
> attr _tilt is private;

BTW, that's:

attr $.tilt;

Attributes are private by default.

Allison

Mike Lambert

unread,
Oct 3, 2002, 3:59:08 PM10/3/02
to Michael G Schwern, perl6-l...@perl.org
> I've been mucking about a bit more with this whole interface thing.
>
> So if we make method signatures only enforced on subclasses if the parent
> class or method has the interface property...
>
> ....except private methods, obviously.
>
> And if we make pre/post conditions and class invariants always enforced...
>
> ....shouldn't we have private invariants and conditions?

Semi-tangential to the point of your message...

With pre/post conditions, a subclass is allowed to weaken the
preconditions or strengthen the postconditions. The postcondition is not
really a problem since one can always add additional checks. However, if
the parent's preconditions apply to the child invariably, it would be
rather difficult to make your subclass accept a wider variety of input.

I'm not proposing a solution, but rather just a problem to keep in mind.

Mike Lambert

Allison Randal

unread,
Oct 3, 2002, 4:45:33 PM10/3/02
to Michael G Schwern, perl6-l...@perl.org
On Thu, Oct 03, 2002 at 03:00:21PM -0400, Michael G Schwern wrote:
> On Thu, Oct 03, 2002 at 02:46:38PM -0400, Michael G Schwern wrote:
> > class ATV is Car, interface {
>
> Hmmm. That should probably be
>
> class ATV isa Car is interface {

That's:

class ATV is Car is interface {

We haven't finally decided how properties will be defined. They may be
subs:

sub *PropertyName is property ($referent, $data) {...}

they may be methods:

method PropertyName is property ($self: $data) {...}

they may be classes:

class PropertyName is Property {...}

# or, like grammar definitions

property PropertyName {...}

or they may be some variation on these or something else entirely.
However they're defined, they will be clearly marked internally as
properties, so there's little risk of confusing property attachment with
inheritance.


Allison

Michael Lazzaro

unread,
Oct 3, 2002, 5:29:57 PM10/3/02
to Allison Randal, Michael G Schwern, perl6-l...@perl.org

> Makes sense, no?

I like that quite a lot.

One question I still have is the syntax of pre/post conditions, e.g:

> method turn($direction, $how_sharp) {
> pre { $how_sharp <= 20 } is private;
> ...implementation...
> }

This is obviously how it would fall out from Apocalypse 4, "pre/post"
being basically types of exception, but I keep having nagging concerns
about it. To me, this keeps looking like "pre { ... }" is a
precondition attached to the _implementation_ of the given method, not
the _signature_ of a given method... For the "is private" case above,
it doesn't make much difference, but I keep thinking something like the
below just feels wonky (?)...

class Vehicle is interface {
attr $tilt;
attr $min_sharpness;

method turn($direction, $how_sharp) {
pre { $how_sharp <= $self.min_sharpness }
... a default implementation, if desired ...
}
}

class Car is Vehicle {
method turn { # this calls the precondition ...
$self.SUPER.turn( ... ); # ... hopefully not twice? ...
... a derived implementation ...
}
}

class Cycle is Vehicle {
method turn { # does this call the precondition? YES?
... a completely alternative implementation that doesn't call super
....
}
}

Do you think it's sufficiently clear to newbies that the pre { } is
associated with the "signature" of the turn() interface method, and not
just the _implementation_ of turn() in Vehicle? e.g. I want a
precondition associated with turn() that is called for _all_
subclasses, whether they call the superclass implementation of turn()
or not, is it clear that that's going on? _IS_ it going on, in the
above?


On Thursday, October 3, 2002, at 01:11 PM, Allison Randal wrote:
> BTW, that's:
> attr $.tilt;
> Attributes are private by default.

(As a lame aside, are we going to have a concept of "private" vs.
"protected" vs. "public", or just private/public? (In other words,
does "private" permit access by subclasses?) Not recommending it, just
wondering if anyone thinks we need it.)

MikeL

Michael G Schwern

unread,
Oct 3, 2002, 5:19:53 PM10/3/02
to Mike Lambert, perl6-l...@perl.org
On Thu, Oct 03, 2002 at 03:59:08PM -0400, Mike Lambert wrote:
> With pre/post conditions, a subclass is allowed to weaken the
> preconditions or strengthen the postconditions.

How exactly does one "weaken" a precondition?


--

Michael G. Schwern <sch...@pobox.com> http://www.pobox.com/~schwern/
Perl Quality Assurance <per...@perl.org> Kwalitee Is Job One

Home of da bomb

Trey Harris

unread,
Oct 3, 2002, 5:27:17 PM10/3/02
to Allison Randal, Michael G Schwern, perl6-l...@perl.org
In a message dated Thu, 3 Oct 2002, Allison Randal writes:

> However they're defined, they will be clearly marked internally as
> properties, so there's little risk of confusing property attachment with
> inheritance.

....except that they seem to share a single namespace, since both
user-defined properties and classes have the naming convention of an
initial capital letter and following mixed-case word characters.

Since they're both introduced with C<is>, you may be able to define both a
property C<Foo> and a class C<Foo>, but you wouldn't be able to use them
both, right?

Incidentally, has there been any headway made on how you DO access
multiple classes with the same name, since Larry has (indirectly) promised
us that? I.e., I import two classes "LinkedList" and "BTree", both of
which define a "Node" class?

Trey


Allison Randal

unread,
Oct 3, 2002, 5:40:35 PM10/3/02
to Michael G Schwern, perl6-l...@perl.org
On Thu, Oct 03, 2002 at 05:14:22PM -0400, Michael G Schwern wrote:

> On Thu, Oct 03, 2002 at 03:45:33PM -0500, Allison Randal wrote:
> > On Thu, Oct 03, 2002 at 03:00:21PM -0400, Michael G Schwern wrote:
> > > On Thu, Oct 03, 2002 at 02:46:38PM -0400, Michael G Schwern wrote:
> > > > class ATV is Car, interface {
> > >
> > > Hmmm. That should probably be
> > >
> > > class ATV isa Car is interface {
> >
> > That's:
> >
> > class ATV is Car is interface {
>
> Wouldn't this mean that class names and property names will inevitably
> clash, so you can't have a class and a property with the same name?

Yes. But if properties are classes (the generally favored solution, at
least until Zurich), that's to be expected.

So far, classes are uppercase and properties are lowercase, but that's
convention, not law.

Allison

Michael G Schwern

unread,
Oct 3, 2002, 5:14:22 PM10/3/02
to Allison Randal, perl6-l...@perl.org
On Thu, Oct 03, 2002 at 03:45:33PM -0500, Allison Randal wrote:
> On Thu, Oct 03, 2002 at 03:00:21PM -0400, Michael G Schwern wrote:
> > On Thu, Oct 03, 2002 at 02:46:38PM -0400, Michael G Schwern wrote:
> > > class ATV is Car, interface {
> >
> > Hmmm. That should probably be
> >
> > class ATV isa Car is interface {
>
> That's:
>
> class ATV is Car is interface {

Wouldn't this mean that class names and property names will inevitably


clash, so you can't have a class and a property with the same name?


--

Michael G. Schwern <sch...@pobox.com> http://www.pobox.com/~schwern/
Perl Quality Assurance <per...@perl.org> Kwalitee Is Job One

The key, my friend, is hash browns.
http://www.goats.com/archive/980402.html

Trey Harris

unread,
Oct 3, 2002, 5:30:49 PM10/3/02
to Michael G Schwern, Mike Lambert, perl6-l...@perl.org
In a message dated Thu, 3 Oct 2002, Michael G Schwern writes:

> On Thu, Oct 03, 2002 at 03:59:08PM -0400, Mike Lambert wrote:
> > With pre/post conditions, a subclass is allowed to weaken the
> > preconditions or strengthen the postconditions.
>
> How exactly does one "weaken" a precondition?

You weaken a precondition by adding ORs; you strengthen a postcondition by
adding ANDs.

Trey

Garrett Goebel

unread,
Oct 3, 2002, 5:47:26 PM10/3/02
to Michael G Schwern, perl6-l...@perl.org
Michael G Schwern:

>
> I've been mucking about a bit more with this whole interface thing.
>
> So if we make method signatures only enforced on subclasses
> if the parent class or method has the interface property...
>
> ....except private methods, obviously.
>
> And if we make pre/post conditions and class invariants
> always enforced...

no.

post-conditions and invariants are always enforced, but pre-conditions are
different. A derived interface can loosen input constraints... so it must be
able to either satisfy all inherited pre-conditions _or_ its own
pre-conditions.


> ....shouldn't we have private invariants and conditions?

no.

I should inject that I disagree with the use of term private as meaning
non-inheritable. I think of private as an methods and attributes accessible
only within the namespace of that class or its descendants. Perhaps a better
term would be something like:

method foo is disinherited { ... }


I also need to separate out the DBC topic from the interface one. For
instance I have a hard time thinking about attributes in the context of
interfaces. For me, interfaces should be limited to a bunch of abstract
methods with conditions. Any other declarations within an interface IMO
should be errors. I.e., all other declarations belong in the implementation
class...

If you want to have a public and private "inheritable" interfaces that's
fine. But what's the point of a non-inheritable interface? Myself, I call
non-inheritable methods "functions".


> class ATV is Car, interface {

> attr _tilt is private;
> invar { ._tilt <= 20 } is private;
>

> method turn($direction, $how_sharp) {
> pre { $how_sharp <= 20 } is private;
> ...implementation...
> }
> }

An interface shouldn't have attributes. And per above, private
pre-conditions are pointless. I would rewrite the above as:

class ATV is Car, interface {

invar { .tilt <= 20 };
method tilt() is private; # in the "to class heirachy" sense
method turn($direction, $how_sharp) {
pre { $how_sharp <= 20 };
}
}


> I've implemented an ATV where I've put in a saftey
> protection against rolling over in a turn as both an
> invariant and a pre-condition. It will not allow you
> to turn the car too sharply, else it simply blows up.
> Wait second... ;)
>
> But I don't want my subclasses to be constrained by that.
> It's just an implementation detail that I only wish to
> enforce upon ATV and not it's children. So they're
> private.
>
> Makes sense, no?

No. Per DBC, pre-conditions are satisfied if either the inherited
pre-conditions _or_ its own pre-conditions are satisfied. Thus allowing the
loosening of input constraints which I believe is what you're after.


--
Garrett Goebel
IS Development Specialist

ScriptPro Direct: 913.403.5261
5828 Reeds Road Main: 913.384.1008
Mission, KS 66202 Fax: 913.384.2180
www.scriptpro.com gar...@scriptpro.com

Garrett Goebel

unread,
Oct 3, 2002, 5:54:13 PM10/3/02
to Garrett Goebel, Michael G Schwern, perl6-l...@perl.org
Garrett Goebel:
> Michael G Schwern:

> > But I don't want my subclasses to be constrained by that.
> > It's just an implementation detail that I only wish to
> > enforce upon ATV and not it's children.

implementation details don't belong in interfaces

Trey Harris

unread,
Oct 3, 2002, 5:49:53 PM10/3/02
to Allison Randal, Michael G Schwern, perl6-l...@perl.org
In a message dated Thu, 3 Oct 2002, Allison Randal writes:
> So far, classes are uppercase and properties are lowercase, but that's
> convention, not law.

Do runtime (value) properties and compile-time (variable) properties share
the same namespace?

That is, to go back to an earlier discussion, if there is a system-defined
value property C<true> which marks a value as true in boolean contexts,
can I also define a compile-time property C<true> that makes the variable
evaluate as true, whatever its value?

Trey

Jonathan Scott Duff

unread,
Oct 3, 2002, 6:23:08 PM10/3/02
to Michael Lazzaro, Allison Randal, Michael G Schwern, perl6-l...@perl.org
On Thu, Oct 03, 2002 at 02:29:57PM -0700, Michael Lazzaro wrote:
> One question I still have is the syntax of pre/post conditions, e.g:
>
> > method turn($direction, $how_sharp) {
> > pre { $how_sharp <= 20 } is private;
> > ...implementation...
> > }
>
> This is obviously how it would fall out from Apocalypse 4, "pre/post"
> being basically types of exception, but I keep having nagging concerns
> about it. To me, this keeps looking like "pre { ... }" is a
> precondition attached to the _implementation_ of the given method, not
> the _signature_ of a given method...

I don't know, but I think it's supposed to be like this:

# part of the signature
method turn($dir,$ang) is pre { $ang <= 20 } {
...
}

# part of the implementation
method turn($dir,$ang) {
PRE { $ang <= 20 }
...
}

turn() methods of derived classes would inherit the precondition in the
first case but not the second. I don't know why you'd want to do this
exactly, but it seems to me that perl should allow it.

> On Thursday, October 3, 2002, at 01:11 PM, Allison Randal wrote:
> > BTW, that's:
> > attr $.tilt;
> > Attributes are private by default.
>
> (As a lame aside, are we going to have a concept of "private" vs.
> "protected" vs. "public", or just private/public? (In other words,
> does "private" permit access by subclasses?) Not recommending it, just
> wondering if anyone thinks we need it.)

I don't think we should be actively reproducing C++'s mistakes :-)

With the constructs shown so far, I can guess that it should be
possible for someone to implement "protected" if they wanted it.

-Scott
--
Jonathan Scott Duff
du...@cbi.tamucc.edu

Paul Johnson

unread,
Oct 3, 2002, 6:18:36 PM10/3/02
to Michael Lazzaro, Allison Randal, Michael G Schwern, perl6-l...@perl.org
On Thu, Oct 03, 2002 at 02:29:57PM -0700, Michael Lazzaro wrote:

> (As a lame aside, are we going to have a concept of "private" vs.
> "protected" vs. "public", or just private/public?

No protected. Even Stroustrup admits it was a mistake in D&E.

--
Paul Johnson - pa...@pjcj.net
http://www.pjcj.net

Michael G Schwern

unread,
Oct 3, 2002, 6:46:14 PM10/3/02
to du...@pobox.com, Michael Lazzaro, Allison Randal, perl6-l...@perl.org
On Thu, Oct 03, 2002 at 05:23:08PM -0500, Jonathan Scott Duff wrote:
> I don't know, but I think it's supposed to be like this:
>
> # part of the signature
> method turn($dir,$ang) is pre { $ang <= 20 } {
> ...
> }
>
> # part of the implementation
> method turn($dir,$ang) {
> PRE { $ang <= 20 }
> ...
> }
>
> turn() methods of derived classes would inherit the precondition in the
> first case but not the second. I don't know why you'd want to do this
> exactly, but it seems to me that perl should allow it.

I see us already smashing too many things into the method signature as it
is. It will rapidly get messy if you have a method with a complex signature
and a handful of attributes and preconditions.

Also, where do the postconditions go? In the signature at the front? That
doesn't make sense, it should go at the end so you can keep them in mind
when you're writing the return code.

Consider...

method foo($this, $that) is memoized is something
is pre { $this <= 42 }
is pre { $that == $this / 2 }
is pre { a lot of code which is hard to
shove into a block of code
this close to the right margin }
is post { what is a post condition
doing at the front? }
{
...
}

They can, of course, be pulled back from the margin:

method foo($this, $that) is memoized is something
is pre { $this <= 42 }
is pre { $that == $this / 2 }
is pre { now we have a little bit more room to play with using
a differnt indentation style }
is post { but post conditions are still distanced from the
code which return()s }
{
...
}

I realize that conditions are technically part of the signature, but putting
them in there paints us into a stylistic corner.

I'm also not fond of the pre/PRE distinction. Few of the other special
blocks (given, eval, try, invar, etc...) use all cap names. At least I hope
not. Simply attaching an "is private" attribute to a pre condition block
seems the simplest way to go about it. Just like any other private thing,
it's not inherited and not visible outside the current class. "pre" vs
"PRE" doesn't convey that meaning.


--

Michael G. Schwern <sch...@pobox.com> http://www.pobox.com/~schwern/
Perl Quality Assurance <per...@perl.org> Kwalitee Is Job One

AY! The ground beef, she is burning my groin!
http://sluggy.com/d/990105.html

Michael G Schwern

unread,
Oct 3, 2002, 6:32:58 PM10/3/02
to Garrett Goebel, perl6-l...@perl.org

It's encoded as a private condition, so it's not part of the interface.

I see class invariants and conditions as just powerful, well organized
assertions, so naturally I'm going to want to use them for more than just
specifying an interface contract. In this case, I'm using them to ensure
that internal details of my implementation are kept in order. It would be
silly to have to define a whole new syntax for that purpose, so I just make
them private.


--

Michael G. Schwern <sch...@pobox.com> http://www.pobox.com/~schwern/
Perl Quality Assurance <per...@perl.org> Kwalitee Is Job One

The eye opening delightful morning taste of expired cheese bits in sour milk!

Michael G Schwern

unread,
Oct 3, 2002, 6:48:16 PM10/3/02
to Michael Lazzaro, Allison Randal, perl6-l...@perl.org
On Thu, Oct 03, 2002 at 02:29:57PM -0700, Michael Lazzaro wrote:
> Do you think it's sufficiently clear to newbies that the pre { } is
> associated with the "signature" of the turn() interface method, and not
> just the _implementation_ of turn() in Vehicle?

The rule would be pretty simple to teach and remember, "conditions and
invariants are inherited unless made private".


--

Michael G. Schwern <sch...@pobox.com> http://www.pobox.com/~schwern/
Perl Quality Assurance <per...@perl.org> Kwalitee Is Job One

It's Flypaper Licking time!

Michael G Schwern

unread,
Oct 3, 2002, 6:49:17 PM10/3/02
to Trey Harris, Mike Lambert, perl6-l...@perl.org

As expressions in Perl run a tad beyond simple boolean logic, could you give
a concrete example?


--

Michael G. Schwern <sch...@pobox.com> http://www.pobox.com/~schwern/
Perl Quality Assurance <per...@perl.org> Kwalitee Is Job One

My beverage utensil experiences a volume crisis.

Michael G Schwern

unread,
Oct 3, 2002, 7:16:09 PM10/3/02
to Garrett Goebel, perl6-l...@perl.org
On Thu, Oct 03, 2002 at 04:47:26PM -0500, Garrett Goebel wrote:
> > And if we make pre/post conditions and class invariants
> > always enforced...
>
> no.
>
> post-conditions and invariants are always enforced, but pre-conditions are
> different.

Right, right.

> A derived interface can loosen input constraints... so it must be
> able to either satisfy all inherited pre-conditions _or_ its own
> pre-conditions.

Looking around, this seems to be regarded as something of a compromise
because truly determining what a real logical weaking is is hard. Are there
other ways to do it, just to mull them over?


> > ....shouldn't we have private invariants and conditions?
>
> no.

Ummm, why?


> I should inject that I disagree with the use of term private as meaning
> non-inheritable. I think of private as an methods and attributes accessible
> only within the namespace of that class or its descendants.

Isn't that "protected"?

As I understand it, Perl 6's private will be non-inheritable methods
accessable only inside the class which defined it. Ruby does it this way,
AFAIK.


> Perhaps a better
> term would be something like:
>
> method foo is disinherited { ... }

is disowned
is get_a_haircut_and_a_job
is i_have_no_son

;)


> I also need to separate out the DBC topic from the interface one. For
> instance I have a hard time thinking about attributes in the context of
> interfaces. For me, interfaces should be limited to a bunch of abstract
> methods with conditions. Any other declarations within an interface IMO
> should be errors. I.e., all other declarations belong in the implementation
> class...

I hope we're not going to explicitly seperate interfaces from
implementation. ie. That you can define an interface at the same time as
you implement it. This is something I really like about Perl as opposed
to other OO systems, class definition and implementation are not kept
seperate.

class Human is interface {
attr head, shoulders, knees, toes;
invar { .head == 1 }
invar { .shoulders == 2 }
invar { .knees == 2 }
invar { .toes == 10 }

method talk ($say,$how_loud) {
$say.uc if $how_loud >= 10:
print "$say\n";
}
}

Of course, if "interfaces" in the Java sense are just classes with no
implementation details, there's no reason why you can't do it seperately.

class AbstractHuman is interface {
attr head, shoulders, knees, toes;
invar { .head == 1 }
invar { .shoulders == 2 }
invar { .knees == 2 }
invar { .toes == 10 }

method talk ($say,$how_loud);
}

class Human isa AbstractHuman {
method talk ($say,$how_loud) {
$say.uc if $how_loud >= 10:
print "$say\n";
}
}

The above would result in the same thing. The latter explicitly seperates
the interface from the implementation, as some like, while the former does
them all in one class, as others like.


> If you want to have a public and private "inheritable" interfaces that's
> fine. But what's the point of a non-inheritable interface? Myself, I call
> non-inheritable methods "functions".

"Interface" is not quite simply the union of "method signature",
"conditions" and "invariants". Interfaces are a combination of the three,
true, but it's only a subset of their use. They're all useful beyond simply
enforcing how subclasses are designed and implemented.

Method signatures are obviously used to define how methods are to be called
by outside users of the object, as well as change the contexts in which the
arguments are parsed.

Pre/post conditions and invariants, when private (ie. not inherited) can be
used like assertions, guaranteeing that internal state and implementation
details are kept sane. My ATV example may not have been clear enough in
that I considered the tilt check to be an internal state check and not a
documented feature of the object. A clearer example might be something like
checking that an internal data structure used by the object is not circular.
A class invariant, yet not something I want to enforce on my children.

They're tools that when combined form an "interface" but are still useful
seperately.


--

Michael G. Schwern <sch...@pobox.com> http://www.pobox.com/~schwern/
Perl Quality Assurance <per...@perl.org> Kwalitee Is Job One

Michael Lazzaro

unread,
Oct 3, 2002, 6:54:09 PM10/3/02
to perl6-l...@perl.org

On Thursday, October 3, 2002, at 03:18 PM, Paul Johnson wrote:
>> (As a lame aside, are we going to have a concept of "private" vs.
>> "protected" vs. "public", or just private/public?
>
> No protected. Even Stroustrup admits it was a mistake in D&E.
Oh, thank God. I was hoping people would say that.

OK, for an entirely different thread...

Is there an accepted preliminary syntax for OO delegation? (I've
looked and can't find anything definitive.) By "delegation", I mean
two different things (you can tell OO programming has firmly arrived by
the fact that, Babel-like, no group of people can ever agree on the
meaning of any given term, making all conversations painful).

1) Delegation through inheritance:
(a.k.a. "mixin" classes, "hard delegation", "concrete interfaces",
etc., etc.)

Example: I want to say that a class DataManager has the capabilities
of the interfaces DataStrategy and CacheStrategy, but is not strictly a
"subclass" of either. In other languages, this might appear like:

class DataManager implements DataStrategy, CacheStrategy { ... }
- or -
class DataManager mixin DataStrategy, CacheStrategy { ... }

(yes, I know you probably wouldn't do a Manager/Strategy like that.
it's just an example, and my mind is blanking right now...)


2) Delegation through attribute:
(a.k.a.... "soft delegation", "instance-based delegation", etc., etc.)

The ability to specify that, if an instance of an object DataSnippet
is affiliated with a specific, runtime instance of a DataManager, e.g.

class DataSnippet {
attr $data_manager is DataManager;
}

... then [some, all] public methods of $self.data_manager can
automatically be delegated by the DataSnippet to that specific
instance, eliminating the need for code that makes you want
to kill yourself:

method foo (...) { $self.data_manager.foo( ... ) }
method bar (...) { $self.data_manager.bar( ... ) }
# ... repeat until carpel tunnel syndrome sets in ...

I have no *good* syntax proposals for this, I don't think I've ever
seen the problem solved with syntax that I really ever liked.

MikeL

Garrett Goebel

unread,
Oct 3, 2002, 7:01:59 PM10/3/02
to Michael G Schwern, Trey Harris, Mike Lambert, perl6-l...@perl.org
Michael G Schwern:

> On Thu, Oct 03, 2002 at 05:30:49PM -0400, Trey Harris wrote:
> > In a message dated Thu, 3 Oct 2002, Michael G Schwern writes:
> >
> > > On Thu, Oct 03, 2002 at 03:59:08PM -0400, Mike Lambert wrote:
> > > > With pre/post conditions, a subclass is allowed to weaken the
> > > > preconditions or strengthen the postconditions.
> > >
> > > How exactly does one "weaken" a precondition?
> >
> > You weaken a precondition by adding ORs; you strengthen a
> postcondition by adding ANDs.
>
> As expressions in Perl run a tad beyond simple boolean logic,
> could you give a concrete example?

all inherited pre-conditions pass
or
class' own pre-conditions pass

Michael G Schwern

unread,
Oct 3, 2002, 7:23:14 PM10/3/02
to perl6-l...@perl.org, du...@pobox.com, Michael Lazzaro, Allison Randal
On Thu, Oct 03, 2002 at 06:46:14PM -0400, Michael G Schwern wrote:
> I see us already smashing too many things into the method signature as it
> is. It will rapidly get messy if you have a method with a complex signature
> and a handful of attributes and preconditions.

I think I have my own counter example.

Consider defining an abstract class with an interface and I want to put some
conditions onto an abstract method.

class Abstract::Human is interface {


attr head, shoulders, knees, toes;
invar { .head == 1 }

invar { .shoulders == .knees == .toes == 2 }

method eat ($food) is pre { !$food.isa('Poison') }
is post { .return eq 'Burp' }
}

since I have no method body for eat() I have no choice but to hang it off
the signature as an attribute.

So conditions do have to go on the signature, but I still like the option of
their being in the body as well, especially given the problem of wanting to
put post conditions at the end.


--

Michael G. Schwern <sch...@pobox.com> http://www.pobox.com/~schwern/
Perl Quality Assurance <per...@perl.org> Kwalitee Is Job One

Cottleston, Cottleston, Cottleston Pie.
A fly can't bird, but a bird can fly.
Ask me a riddle and I reply:
"Cottleston, Cottleston, Cottleston Pie."

Michael G Schwern

unread,
Oct 3, 2002, 7:25:50 PM10/3/02
to Michael Lazzaro, perl6-l...@perl.org
On Thu, Oct 03, 2002 at 03:54:09PM -0700, Michael Lazzaro wrote:
> I have no *good* syntax proposals for this, I don't think I've ever
> seen the problem solved with syntax that I really ever liked.

Class::Delegation?


--

Michael G. Schwern <sch...@pobox.com> http://www.pobox.com/~schwern/
Perl Quality Assurance <per...@perl.org> Kwalitee Is Job One

MERV GRIFFIN!

Michael G Schwern

unread,
Oct 3, 2002, 7:28:39 PM10/3/02
to perl6-l...@perl.org
On Thu, Oct 03, 2002 at 07:23:14PM -0400, Michael G Schwern wrote:
> invar { .shoulders == .knees == .toes == 2 }

This may explain why I can only count to 12 with my shoes off.

As this is my 3rd reply to myself in the thread, I'll call it a night. :)


--

Michael G. Schwern <sch...@pobox.com> http://www.pobox.com/~schwern/
Perl Quality Assurance <per...@perl.org> Kwalitee Is Job One

If the women don't find you handsome, they should at least find you handy.
-- Red Green

Michael Lazzaro

unread,
Oct 3, 2002, 8:52:37 PM10/3/02
to Michael G Schwern, perl6-l...@perl.org
On Thursday, October 3, 2002, at 04:25 PM, Michael G Schwern wrote:

> On Thu, Oct 03, 2002 at 03:54:09PM -0700, Michael Lazzaro wrote:
>> I have no *good* syntax proposals for this, I don't think I've ever
>> seen the problem solved with syntax that I really ever liked.
>
> Class::Delegation?

Yeah, it's one of the best I've seen: it makes sense, does everything I
want, and is easy to explain even to newbies. The perl5 hash-based
syntax is still pretty scary, tho.

Dunno, I keep wishing for something that's a one-liner for simple
cases. I guess something like:

# $.data_manager receives all method calls for which
# it has a matching public interface.

class DataSnippet {
attr $data_manager is DataManager receives ( -ALL );
}

# alternative syntax, also useful on a method-by-method basis...
# Note that if steer() has an implementation, it's dispatched there
too.

class Car is interface {
attr $left_front_wheel;
attr $right_front_wheel;
...

method steer ( ... ) is dispatched( $left_front_wheel,
$right_front_wheel ) { ... };
}

Incidentally, I think the Car above is an example of why it might be ok
to allow attributes in interfaces. (I would definitely argue it's ok
to give default method implementations in interfaces. You don't have
to if you don't believe in it, but hey, some people prefer it.) You're
basically saying that the interface attaches these named attribs to
anything that use it. It usually isn't considered proper, but I don't
know if it's evil enough to explicitly disallow.

The biggest problem I see with interface attribs myself is
implementational, not philosophical; if you've got attribs being
assembled from multiple interfaces, it makes implementation of
subclasses even more difficult to optimize. (Of course, we already
have multiple inheritance, so that ship's probably long sailed already.)

MikeL

John Williams

unread,
Oct 3, 2002, 9:59:33 PM10/3/02
to Michael Lazzaro, perl6-l...@perl.org
On Thu, 3 Oct 2002, Michael Lazzaro wrote:
>
> 1) Delegation through inheritance:
> (a.k.a. "mixin" classes, "hard delegation", "concrete interfaces",
> etc., etc.)
>
> Example: I want to say that a class DataManager has the capabilities
> of the interfaces DataStrategy and CacheStrategy, but is not strictly a
> "subclass" of either. In other languages, this might appear like:
>
> class DataManager implements DataStrategy, CacheStrategy { ... }
> - or -
> class DataManager mixin DataStrategy, CacheStrategy { ... }

Aside from runtime mixin', in what way does inheritance _not_ do what you
want?

> 2) Delegation through attribute:
> (a.k.a.... "soft delegation", "instance-based delegation", etc., etc.)
>
> The ability to specify that, if an instance of an object DataSnippet
> is affiliated with a specific, runtime instance of a DataManager, e.g.
>
> class DataSnippet {
> attr $data_manager is DataManager;
> }
>
> ... then [some, all] public methods of $self.data_manager can
> automatically be delegated by the DataSnippet to that specific
> instance, eliminating the need for code that makes you want
> to kill yourself:
>
> method foo (...) { $self.data_manager.foo( ... ) }
> method bar (...) { $self.data_manager.bar( ... ) }
> # ... repeat until carpel tunnel syndrome sets in ...

Reaction #1: Only on a perl list would it occur to people to complain
about that. :)

Reaction #2: Inheritance would automatically delegate all those
methods, so again, in what way does inheritance _not_ solve the problem?


Finally, a question about interfaces:
In what way is an interface different from a pure abstract class (i.e.
containing only method declarations, but no code)?

~ John Williams

DISCLAIMER: This post assumes perl6 will have multiple inheritance.


John Williams

unread,
Oct 3, 2002, 11:17:20 PM10/3/02
to Trey Harris, perl6-l...@perl.org
On Thu, 3 Oct 2002, Trey Harris wrote:

> Incidentally, has there been any headway made on how you DO access
> multiple classes with the same name, since Larry has (indirectly) promised
> us that? I.e., I import two classes "LinkedList" and "BTree", both of
> which define a "Node" class?

Hopefully, LinkedList defines a LinkedList::Node class, and BTree defines
a BTree::Node class. Either by explicitly naming them that or by virtue
of being defined as an "inner" class (which might also make it private).

~ John Williams

John Williams

unread,
Oct 3, 2002, 11:10:23 PM10/3/02
to Allison Randal, perl6-l...@perl.org
On Thu, 3 Oct 2002, Allison Randal wrote:

> On Thu, Oct 03, 2002 at 03:00:21PM -0400, Michael G Schwern wrote:
> > On Thu, Oct 03, 2002 at 02:46:38PM -0400, Michael G Schwern wrote:
> > > class ATV is Car, interface {
> >
> > Hmmm. That should probably be
> >
> > class ATV isa Car is interface {
>
> That's:
>
> class ATV is Car is interface {

I'd vote that properties be implemented as classes (see below), which
prompts the question, How does one distinguish between a property class
which inherits from another property class, and a property class which
'is' some property? Or perhaps there is no difference, because
property-ness is actually implemented via inheritance?

> We haven't finally decided how properties will be defined. They may be
> subs:

> they may be methods:
> they may be classes:

I came to the class implementation conclusion when thinking about runtime
properties. Things like "but tainted" obviously need to propogate when
operations are performed on them, so other properties, such as "but
true/but false", may want to propogate as well. However the rules for
propogating "tainted" (result is always tainted) are different from
true/false (propogate according to boolean logic) are different from
'but We_better_call_ya("Bruce")' (never, ever propogate).

So the obvious way to implement that is via operator overloading for the
property classes. If two values have properties of the same type, the
same operation performed on the values is performed on the properties.

5 but false + 3 but false == (5 + 3) but (false + false)

If only one value has a property, the right thing to do is not entirely
clear. Maybe in (5 but false + 3) the false property is combined with the
boolean conversion of 3 (true). Or undef if the conversion is not
possible. Or maybe I'm rambling on too long...

~ John Williams

Trey Harris

unread,
Oct 4, 2002, 12:03:44 AM10/4/02
to John Williams, perl6-l...@perl.org

Ah, but that's the way you do it now--name the classes differently.
(Easy--assuming you control the source code!) In Perl 6, we're supposed
to be able to use multiple versions of the same class concurrently, which
I think would imply also being able to use multiple classes that happened
to be named the same thing.

Trey

Michael G Schwern

unread,
Oct 4, 2002, 12:34:50 AM10/4/02
to John Williams, Michael Lazzaro, perl6-l...@perl.org
On Thu, Oct 03, 2002 at 07:59:33PM -0600, John Williams wrote:
> Reaction #2: Inheritance would automatically delegate all those
> methods, so again, in what way does inheritance _not_ solve the problem?

I don't think p6l is the right place to discuss the merits of delegation,
let's just say it's a Good Thing to have in your OO toolbelt. Solves a lot
of problems which would otherwise require hairy, ambiguous multiple
inheritance situations. If you're curious I can explain more off-list.


> Finally, a question about interfaces:
> In what way is an interface different from a pure abstract class (i.e.
> containing only method declarations, but no code)?

An interface requires subclassers to implement all abstract methods and they
must match the method signatures, conditions and invariants of the
interface.

A pure abstract class doesn't necessarily require subclasses to do anything,
at least not in Perl.

So an interface is simply a class, maybe abstract, which requires its
subclasses to conform to its signature.

At least that's how I see it.


--

Michael G. Schwern <sch...@pobox.com> http://www.pobox.com/~schwern/
Perl Quality Assurance <per...@perl.org> Kwalitee Is Job One

It's Airplane Glue sniffing time!

Trey Harris

unread,
Oct 4, 2002, 12:28:29 AM10/4/02
to Michael Lazzaro, Michael G Schwern, perl6-l...@perl.org
In a message dated Thu, 3 Oct 2002, Michael Lazzaro writes:

> On Thursday, October 3, 2002, at 04:25 PM, Michael G Schwern wrote:
> > Class::Delegation?
>
> Yeah, it's one of the best I've seen: it makes sense, does everything I
> want, and is easy to explain even to newbies. The perl5 hash-based
> syntax is still pretty scary, tho.
>
> Dunno, I keep wishing for something that's a one-liner for simple
> cases. I guess something like:
>
> # $.data_manager receives all method calls for which
> # it has a matching public interface.
>
> class DataSnippet {
> attr $data_manager is DataManager receives ( -ALL );
> }

Looks like a simple Perl 6 grammar munge to me--it's a simple postfix
conditional which takes the declaration before it, gets its type (or looks
at the code, TMTOWTDI) and creates accessors in the namspace of the
caller. Doesn't appear particularly magical to me. In fact, if you
didn't mind writing it

attr data_manager => DataManager, receives => -ALL;

you could easily write it in Perl 5 today.

>
> # alternative syntax, also useful on a method-by-method basis...
> # Note that if steer() has an implementation, it's dispatched there
> too.
>
> class Car is interface {
> attr $left_front_wheel;
> attr $right_front_wheel;
> ...
>
> method steer ( ... ) is dispatched( $left_front_wheel,
> $right_front_wheel ) { ... };
> }

This is doable now too:

dispatch steer => $left_front_wheel, $right_front_wheel;

Could be written in Perl 5, simply enough, as

sub dispatch {
no strict 'refs';
my ($method, @dispatchees) = @_;
*{caller()."::$_[0]"} =
sub {
$_->$method(@_) foreach @dispatchees;
};
}

I think my point here is that there are clearly places where we need
stronger built-in support in Perl of some OO concepts. Delegation may not
be one of them--it's easy enough to graft on, and TMTOWTDI may be good
here.

> Incidentally, I think the Car above is an example of why it might be ok
> to allow attributes in interfaces. (I would definitely argue it's ok
> to give default method implementations in interfaces. You don't have
> to if you don't believe in it, but hey, some people prefer it.) You're
> basically saying that the interface attaches these named attribs to
> anything that use it. It usually isn't considered proper, but I don't
> know if it's evil enough to explicitly disallow.
>
> The biggest problem I see with interface attribs myself is
> implementational, not philosophical; if you've got attribs being
> assembled from multiple interfaces, it makes implementation of
> subclasses even more difficult to optimize. (Of course, we already
> have multiple inheritance, so that ship's probably long sailed already.)

I don't understand. A public attribute will have an autocreated accessor.
So put the accessor in the interface, not the attribute. If you put the
attribute in the interface, you've committed to having it as an attribute.
If you decide to turn it into a computed method, you're out of
luck--unless you make the attribute a tied variable itself (gak!).

Trey

Michael G Schwern

unread,
Oct 4, 2002, 12:37:27 AM10/4/02
to Trey Harris, Michael Lazzaro, perl6-l...@perl.org
On Fri, Oct 04, 2002 at 12:28:29AM -0400, Trey Harris wrote:
> I think my point here is that there are clearly places where we need
> stronger built-in support in Perl of some OO concepts. Delegation may not
> be one of them--it's easy enough to graft on, and TMTOWTDI may be good
> here.

Delegation is a basic OO technique. We definately should have fast,
well-designed core support for it.


--

Michael G. Schwern <sch...@pobox.com> http://www.pobox.com/~schwern/
Perl Quality Assurance <per...@perl.org> Kwalitee Is Job One

Is there an airport nearby or is that just my tae-kwon-do taking off?

Mike Lambert

unread,
Oct 4, 2002, 12:58:54 AM10/4/02
to Michael G Schwern, perl6-l...@perl.org
Michael G Schwern wrote:

> How exactly does one "weaken" a precondition?

Say I define a mathematical mod() function in my parent number class.

precondition: $a > 0, $b > 0, $b is int
mod( $a, $b )

Then in my subclass, I want to make it work in a wider variety of
contexts. I change the definition to:

precondition: $b is int, $b != 0
mod( $a, $b )

It now properly supports modulo arithmetic for negative numbers, because
the requirements for running the function have been weakened. It is still
completely substitutable anywhere that the parent implementation would
work, but if code is dealing with my subclass it is allowed to work with
the weakened precondition.

Since your proposal was based upon the idea of having every parent
condition apply to child implementations, the possibility for strengthened
postconditions falls out of the proposal nicely. But since preconditions
work in the opposite direction, they don't quite gel with that particular
proposal.

Mike Lambert


Trey Harris

unread,
Oct 4, 2002, 1:06:45 AM10/4/02
to Garrett Goebel, Michael G Schwern, Mike Lambert, perl6-l...@perl.org
In a message dated Thu, 3 Oct 2002, Garrett Goebel writes:

> Michael G Schwern:
> > On Thu, Oct 03, 2002 at 05:30:49PM -0400, Trey Harris wrote:
> > > In a message dated Thu, 3 Oct 2002, Michael G Schwern writes:
> > >
> > > > On Thu, Oct 03, 2002 at 03:59:08PM -0400, Mike Lambert wrote:
> > > > > With pre/post conditions, a subclass is allowed to weaken the
> > > > > preconditions or strengthen the postconditions.
> > > >
> > > > How exactly does one "weaken" a precondition?
> > >
> > > You weaken a precondition by adding ORs; you strengthen a
> > postcondition by adding ANDs.
> >
> > As expressions in Perl run a tad beyond simple boolean logic,
> > could you give a concrete example?

I don't know what you mean. How can a precondition be anything but
boolean?

> all inherited pre-conditions pass
> or
> class' own pre-conditions pass

I'm afraid I'm a bit lost here. What does "pass" mean besides "evaluates
to true in a boolean context"? And if that's what "pass" means, then
can't you just OR the preconditions together, in subclass-to-superclass
order?

Trey

Andy Wardley

unread,
Oct 4, 2002, 4:02:32 AM10/4/02
to John Williams, Michael Lazzaro, perl6-l...@perl.org
John Williams wrote:
> Reaction #2: Inheritance would automatically delegate all those
> methods, so again, in what way does inheritance _not_ solve the problem?

Many real life systems are composed from elements, not inherited from
elements. A car is not a wheel, but is composed from 4 (or more).

As a simple example, a wheel might implement an inflate() method, but
it probably wouldn't make much sense for the car to inherit that
method. Rather, you would define inflate_tyres() which delegates
to the inflate() method on the tyres on each of the the 4 wheels.

Further still, the airbag might also have an inflate() method. If
you're not careful and don't inherit all your objects in exactly
the right order then you might find your tyres inflating instead
of your airbag when you hit a truck.

False inheritance leads to method madness.

> In what way is an interface different from a pure abstract class (i.e.
> containing only method declarations, but no code)?

Inheritance and interfaces are two different things. The end result
would be pretty much the same in this example, but reaching it by
different routes.

With inheritance, your derived object inherits all the methods that
you don't explicity re-define.

With interfaces, you are stating that your object will implement
all the methods, either directly or by inheriting from, or delegating
to other classes.

Thus, inheritance, delegation and interfaces are separate, orthogonal
concepts.

Inheritance : is
Delegation : has
Interface : can


A


Aaron Sherman

unread,
Oct 4, 2002, 9:26:08 AM10/4/02
to Mike Lambert, Perl6 Language List

There are a very large number of good things that I think we should put
into properties for meta-programming purposes (e.g. constraints,
assertions, optimization hints, documentation, etc).

For example:

sub f(int $a is constrained($a>=1,"must be positive),
documented("an integer"))
is constrained(some_global_condition),
documented("applies transformation f to an integer") {
...
}

So, when documentation is extracted from this:

=item C<f($a)>

This function applies transformation f to an integer.

It takes the following parameters:

=over 5

=item C<$a>

This parameter is an integer which must be positive.

=back

Walla! Self-documenting functions.

--
Aaron Sherman <a...@ajs.com>

Chris Dutton

unread,
Oct 4, 2002, 9:13:45 AM10/4/02
to Michael G Schwern, Mike Lambert, perl6-l...@perl.org
On Thursday, October 3, 2002, at 05:19 PM, Michael G Schwern wrote:

> On Thu, Oct 03, 2002 at 03:59:08PM -0400, Mike Lambert wrote:
>> With pre/post conditions, a subclass is allowed to weaken the
>> preconditions or strengthen the postconditions.
>
> How exactly does one "weaken" a precondition?

At least in Eiffel, if you redefine a method, you may not give it
stringer preconditions than the original method, but you may have
stronger postconditions. In essence, you're not requiring any more of
the client, but you can ensure more to them on completion, thus
maintaining the parent's contract.

Dan Sugalski

unread,
Oct 4, 2002, 10:45:52 AM10/4/02
to Michael G Schwern, Trey Harris, Michael Lazzaro, perl6-l...@perl.org
At 12:37 AM -0400 10/4/02, Michael G Schwern wrote:
>Delegation is a basic OO technique. We definately should have fast,
>well-designed core support for it.

I'm pretty sure we will. I certainly need it internally...
--
Dan

--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
d...@sidhe.org have teddy bears and even
teddy bears get drunk

Peter Haworth

unread,
Oct 4, 2002, 11:13:29 AM10/4/02
to Michael G Schwern, Garrett Goebel, perl6-l...@perl.org
On Thu, 3 Oct 2002 19:16:09 -0400, Michael G Schwern wrote:
> On Thu, Oct 03, 2002 at 04:47:26PM -0500, Garrett Goebel wrote:
> > A derived interface can loosen input constraints... so it must be
> > able to either satisfy all inherited pre-conditions _or_ its own
> > pre-conditions.
>
> Looking around, this seems to be regarded as something of a compromise
> because truly determining what a real logical weaking is is hard.

That *is* a logical weakening. Just because the inherited precondition is
C<< x > 10 >>, doesn't mean that the weakened condition has to be of the form
C<< x > 9 >> or any other value lower than 10. C<< a || b >> is weaker than
C<< a >>

> Are there
> other ways to do it, just to mull them over?

--
Peter Haworth p...@edison.ioppublishing.com
"I remember being impressed with Ada because you could write an infinite
loop without a faked up condition. The idea being that in Ada the
typical infinite loop would be normally be terminated by detonation."
-- Larry Wall

Peter Haworth

unread,
Oct 4, 2002, 11:09:19 AM10/4/02
to Michael G Schwern, du...@pobox.com, Michael Lazzaro, Allison Randal, perl6-l...@perl.org
On Thu, 3 Oct 2002 18:46:14 -0400, Michael G Schwern wrote:
> method foo($this, $that) is memoized is something
> is pre { $this <= 42 }
> is pre { $that == $this / 2 }
> is pre { now we have a little bit more room to play with using
> a differnt indentation style }
> is post { but post conditions are still distanced from the
> code which return()s }
> {
> ...
> }
>
> I realize that conditions are technically part of the signature, but putting
> them in there paints us into a stylistic corner.

This is the one nice thing about the Pascal-like syntax of Eiffel. It allows
this situation to be unambiguous and sensibly ordered (as well as giving each
condition labels, so that violations can be better reported):

foo(this: ThisType, that: ThatType): FooType IS
REQUIRE
small: this <= 42
half: that = this / 2
DO
-- implementation goes here
ENSURE
fooed_ok: RESULT = baz(this) + that
END

If you're declaring an abstract feature, just replace the whole DO clause with
"DEFERRED". Also notice how Eiffel's syntax also somehow makes statement
terminators completely optional.

Aren't sub declarations in Perl 6 all expressions? Why couldn't we put the
post condition at the end, then?

sub foo($this, $that) is memoized is something


is pre{ $this <= 42 }
is pre{ $that == $this / 2 }

{
# implementation goes here
} is post{
# postcondition 1
} is post{
# postcondition 2
}

If you want an abstract method, just omit the implementation block.

--
Peter Haworth p...@edison.ioppublishing.com
"Maybe that's [Java's] niche, its a language for people who like pain."
-- Dean Wilson

Garrett Goebel

unread,
Oct 4, 2002, 11:36:13 AM10/4/02
to Michael G Schwern, perl6-l...@perl.org, du...@pobox.com, Michael Lazzaro, Allison Randal
Michael G Schwern:

> Michael G Schwern wrote:
> > I see us already smashing too many things into the
> > method signature as it is. It will rapidly get
> > messy if you have a method with a complex signature
> > and a handful of attributes and preconditions.
>
> I think I have my own counter example.
>
> Consider defining an abstract class with an interface
> and I want to put some conditions onto an abstract
> method.
>
> class Abstract::Human is interface {
> attr head, shoulders, knees, toes;
> invar { .head == 1 }
> invar { .shoulders == .knees == .toes == 2 }
>
> method eat ($food) is pre { !$food.isa('Poison') }
> is post { .return eq 'Burp' }
> }
>
> since I have no method body for eat() I have no choice but to
> hang it off the signature as an attribute.

That wasn't the way I remembered it from Apoc 4... The following example is
not in A4, but its what I inferred from it...

Class Foo {
method eat($food) is abstract {
PRE { ... }
POST { ... }
}
}

Class Bar is Foo {
method eat {
PRE { ... }
... implementation ...
POST { ... }
}
}


'eat' may be an abstract method inherited by Bar from Foo... but the PRE and
POST conditions are still inherited. Though I can see the issue that
abstract precludes an implementation. But does that also require use to
preclude the code block?

Also if you rely on attributes to hang conditions... you're ruling out the
ability to reference things in the lexical context of the code block.

Erik Steven Harrison

unread,
Oct 4, 2002, 11:54:52 AM10/4/02
to perl6-l...@perl.org

--

On Thu, 3 Oct 2002 18:46:14

Michael G Schwern wrote:
>
>I see us already smashing too many things into the method signature as it
>is. It will rapidly get messy if you have a method with a complex signature
>and a handful of attributes and preconditions.

This is the sort of creeping elegance which made me
worry about is/but in the first place.

>
>Also, where do the postconditions go? In the signature at the front?

Well, if pre and post conditions are blocks they don't
have to go in the signature at all. We can affect a
lexical scope outside of the lexical scope, so we can
simply define the PRE and POST blocks lexically to the
method _outside_ of the method. No need to put it in
the signature. Assuming method foo


foo.MY{ PRE } := sub { ... };


This is all contingent on the idea that we can name
lexical scopes (such as with loop labels, named rules
and subs, methods). The precondition here will refer
to whatever method foo is defined, wherever it is
defined in the inheritance heirarchy. If you want to
point to a specific foo, use it's fully qualified
name, if you want to point to a lexically scoped foo


__FILE__.MY{ '&foo' }.MY{ PRE } := sub { ... };
#Ugly, ain't it?


though why you wouldn't want to do it in the method
definition itself is beyond me.


Now this example syntax is ugly intentionally. It's
ugly so that someone smarter than me will feel the
need to fix it. The symbol table, taking a reference
to a class, the %MY stash are all a little vague
anyway, and I'd like to see someone propose good
syntax for it.


-Erik, of the evil mailer


That
>doesn't make sense, it should go at the end so you can keep them in mind
>when you're writing the return code.
>
>Consider...


>
> method foo($this, $that) is memoized is something
> is pre { $this <= 42 }
> is pre { $that == $this / 2 }

> is pre { a lot of code which is hard to
> shove into a block of code
> this close to the right margin }
> is post { what is a post condition
> doing at the front? }
> {
> ...
> }
>
>They can, of course, be pulled back from the margin:


>
> method foo($this, $that) is memoized is something
> is pre { $this <= 42 }
> is pre { $that == $this / 2 }
> is pre { now we have a little bit more room to play with using
> a differnt indentation style }
> is post { but post conditions are still distanced from the
> code which return()s }
> {
> ...
> }
>
>I realize that conditions are technically part of the signature, but putting
>them in there paints us into a stylistic corner.
>

>I'm also not fond of the pre/PRE distinction. Few of the other special
>blocks (given, eval, try, invar, etc...) use all cap names. At least I hope
>not. Simply attaching an "is private" attribute to a pre condition block
>seems the simplest way to go about it. Just like any other private thing,
>it's not inherited and not visible outside the current class. "pre" vs
>"PRE" doesn't convey that meaning.


>
>
>--
>
>Michael G. Schwern <sch...@pobox.com> http://www.pobox.com/~schwern/
>Perl Quality Assurance <per...@perl.org> Kwalitee Is Job One

>AY! The ground beef, she is burning my groin!
> http://sluggy.com/d/990105.html
>


Is your boss reading your email? ....Probably
Keep your messages private by using Lycos Mail.
Sign up today at http://mail.lycos.com

Buddha Buck

unread,
Oct 4, 2002, 12:29:12 PM10/4/02
to Peter Haworth, Michael G Schwern, Garrett Goebel, perl6-l...@perl.org
Peter Haworth wrote:

> That *is* a logical weakening. Just because the inherited precondition is
> C<< x > 10 >>, doesn't mean that the weakened condition has to be of the form
> C<< x > 9 >> or any other value lower than 10. C<< a || b >> is weaker than
> C<< a >>

So what we are looking at is something like....


class Animal {
method eat($food) is abstract {
PRE { $food.isa(Edible); }
POST { !$stomach.empty; }
}
...
}

class Goat is Animal {
method eat($food) {
PRE { $food.isa(Can); }
my $chewedfood = $teeth.chew($food);
$stomach.add($chewefood);
$teeth.brush()
POST { $teeth.clean; }
}
...
}

class Teeth {
method brush {...};
method chew {
...
POST { .clean == false; }
}
}
my Animal $billy = new Goat;

$billy.eat(Banana.new()); # succeeds because PRE for Animal.eat is met
$billy.eat(Can.new()); # succeeds because PRE for Goat.eat is met
$billy.eat(Rock.new()); # Fails because neither PRE is met

class DirtyTeeth is Teeth {
method brush {};
...
}

$billy.teeth = DirtyTeeth.new();
$billy.eat(Banana.new()); # Fails because POST for Goat.eat is not met

etc.

Garrett Goebel

unread,
Oct 4, 2002, 1:37:33 PM10/4/02
to Michael G Schwern, Garrett Goebel, perl6-l...@perl.org
Michael G Schwern:

> Garrett Goebel wrote:
> > A derived interface can loosen input constraints... so
> > it must be able to either satisfy all inherited pre-
> > conditions _or_ its own pre-conditions.
>
> Looking around, this seems to be regarded as something of a
> compromise because truly determining what a real logical
> weaking is is hard. Are there other ways to do it, just to
> mull them over?

I thought about this for a while while reading your post. There are
certainly pre-conditions which you will want to be enforced all the way down
the line. And running counter to this is the need to be able to weaken
pre-condition constraints to handle a wider range of inputs. Which requires
that the derived class not need to satisfy all inherited pre-conditions.

So the following wouldn't necessarily DWIM (if you know what I mean):

Class Foo {
method count($from, $to) {
PRE { $to < 10 }
PRE { $from >= .lower_bound }
}
}
Class Bar is Foo { method count { PRE { .to < 100 } } }
Class Baz is Bar { method count { ... implementation ... } }

if you call Bar->count(-1, 99) you're no longer effectively constraining
$from >= .lower_bound.

if you call Baz->count(-1, 99) you'll fail the Foo precondition. But since
you haven't defined any pre-conditions for Baz does this mean you have to
satisfy all inherited preconditions or that there are none? I.e. where's the
boolean OR logic when inherited pre-conditions are defined, but the derived
class' pre-conditions are undefined?

So currently, you'll need to rewrite all applicable pre-conditions for each
derived class, because you don't know if one of the existing or future
refactorings of a super-classes will weaken the input constraints. So you
can't assume you'll ever successfully pass all inherited pre-conditions.
I.e. you can only trust the class' own pre-conditions.


This is where I get pretty fuzzy. How to address the issue? -Assuming I've
understood it correctly and that it really is an issue. Can anyone back me
up with a yea or neh as to whether or not this is real problem... or just my
misunderstanding?


I wonder if it might be useful to somehow tag a pre-condition to be
invariably enforced ('AND') like post and invariant conditions... or
alternatively marked as overridable ('OR' --the default) to allow loosing
input constraints.

Perhaps replacing the Class Foo example above with:

Class Foo {
method count($from, $to) {
PRE { $to < 10 } # 'is OR' is default
PRE is AND { $from >= .lower_bound }
}
}
Class Bar is Foo { method count { PRE { .to < 100 } } }
Class Baz is Bar { method count { ... implementation ... } }

With two more semantic changes:
o modifying the 'OR'ing of a class' inherited pre-conditions
to be only one inheritence level deep
o a class which has no pre-conditions would be required to
satisfy the inherited pre-conditions (no OR if undef)

So calling Bar->count(-1, 99) where the current class (Bar) has no
pre-conditions would DWIM. I.e., it would have to satisfy the 'OR'
pre-conditions from Bar and the 'AND' pre-condition from Foo.


Have I walked off into la-la land on a foundation of misunderstandings?

Garrett Goebel

unread,
Oct 4, 2002, 2:21:17 PM10/4/02
to John Williams, Michael Lazzaro, perl6-l...@perl.org
John Williams:

> Reaction #2: Inheritance would automatically delegate all those
> methods, so again, in what way does inheritance _not_ solve
> the problem?

What about when you want to be able to dynamically swap the objects to which
you're delegating?

Trey Harris

unread,
Oct 4, 2002, 6:26:31 PM10/4/02
to sch...@pobox.com, Chris Dutton, Mike Lambert, perl6-l...@perl.org
In a message dated Fri, 4 Oct 2002, sch...@pobox.com writes:

> On Fri, Oct 04, 2002 at 09:13:45AM -0400, Chris Dutton wrote:
> > > How exactly does one "weaken" a precondition?
> >
> > At least in Eiffel, if you redefine a method, you may not give it
> > stringer preconditions than the original method, but you may have
> > stronger postconditions. In essence, you're not requiring any more of
> > the client, but you can ensure more to them on completion, thus
> > maintaining the parent's contract.
>

> But what does it mean to be "stronger"? How does Eiffel figure out if
> a given precondition is "stronger" or "weaker" than another?

Like I said before, boolean logic. Preconditions are OR'd together
(starting with the deepest subclass and working back to the most ancestral
class, in order to short-circuit most effectively), postconditions are
AND'd together (in the opposite order, same reason).

You responded that it couldn't work that way in Perl because Perl has
expressions that are more complicated than booleans. I asked you what you
meant by that, since the only definition of "passing a condition" I'm
aware of in Perl is a boolean expression returning true. You haven't
responded to that one yet. :-)

Trey

sch...@pobox.com

unread,
Oct 4, 2002, 6:23:00 PM10/4/02
to Chris Dutton, Mike Lambert, perl6-l...@perl.org
On Fri, Oct 04, 2002 at 09:13:45AM -0400, Chris Dutton wrote:
> > How exactly does one "weaken" a precondition?
>
> At least in Eiffel, if you redefine a method, you may not give it
> stringer preconditions than the original method, but you may have
> stronger postconditions. In essence, you're not requiring any more of
> the client, but you can ensure more to them on completion, thus
> maintaining the parent's contract.

But what does it mean to be "stronger"? How does Eiffel figure out if


a given precondition is "stronger" or "weaker" than another?


--
Michael G Schwern <sch...@pobox.com> http://www.pobox.com/~schwern/

sch...@pobox.com

unread,
Oct 4, 2002, 7:34:31 PM10/4/02
to Garrett Goebel, perl6-l...@perl.org
On Fri, Oct 04, 2002 at 02:44:24PM -0500, Garrett Goebel wrote:
> > > > ....shouldn't we have private invariants and conditions?
> > >
> > > no.
> >
> > Ummm, why?
>
> Maybe I'm just grinding an ax...
>
> If you allow an interface's post conditions and invariants to be overlooked,
> then you've got a broken interface.

***************************
But they're *not part of the interface*
***************************

Just to make it clear. :) Conditions and invariants are part of but
not exclusive to the interface of a class. They're just well-done
assertions. When inherited, they're part of the interface. When
private and used as assertions on implementation detail, they're just
assertions.

The ability to define conditions on a class which must remain true at
all times (mod the details of DBC rules) is very powerful and
shouldn't be limited to simply defining an interface. Pre/post
conditions about implementation details may not be terribly useful,
but class invariants will.


> I think my ax could rest more peacefully if I could see more clearly how the
> syntax would allow us to clearly disambiguate between the interface and the
> implementation; constraints on a method's inputs and outputs as separate
> from how its implemented.

This is what I'm proposing.

invar { .foo eq 'bar' } # interface
invar { .wibble eq 'miff' } is private # implementation

It's inherited by default, and not inherited if declared private.
Same as a method.


> > I hope we're not going to explicitly seperate interfaces from
> > implementation. ie. That you can define an interface at the
> > same time as you implement it. This is something I really
> > like about Perl as opposed to other OO systems, class
> > definition and implementation are not kept seperate.
>
> I hope we do when we explicitly flag a class as an interface. After all, a
> class which isn't explicitly qualified as an interface still has one.

I think the trouble here is that not everyone is going to want method
signatures strictly enforced on their subclasses. So what the default
behavior will be is really a matter of the philosophy of our OO
implementation. Right now I'm assuming signatures will not be
enforced unless you specify the class with an 'interface' property,
but I could go either way.

Conditions and invariants, OTOH, will always be enforced (unless
declared private) otherwise they have little purpose.


> But I suppose that is what your private idea is all about. In the
> context of a class private means "just don't inherit this". In the
> context of an interface private means "this is not part of the
> interface". It still looks like it'll be messy when deep inheritence
> is involved.

Private, how I see it, means "don't inherit this *and* it can't be
used outside the scope of this class". That second bit implies it's
not part of the interface.

To clarify:

class Foo {
method _bar is private {
...
}
method something {
._bar("foo"); # ok, we're inside Foo
}
}

my $foo = Foo.new;
$foo._bar; # not ok. Even though we've got a Foo object,
# we're outside the class declaration and can't
# call private methods.


> However, I would still disagree with allowing private conditions on
> non-private methods. At least not when you're tagging the class with a label
> declaring it to be an interface, since non-private methods are implicitly
> part of the interface.

But the private conditions are not part of the interface, even when
placed on a public method. It's just a fancy assertion. It might
help if you mentally s/private (condition|invariant)/assertion/g to
help think of how they can be used seperate from in an interface.

Just to clarify, in my world implementation and interface do not have
to be seperated. An "interface" is merely a class which enforces it's
method signatures on it's subclasses.


> In short, go ahead and write it in a single class. You know where the
> interface leaves off and the implementation begins. Just don't hang the
> 'Interface' attribute off it.

I think most of what we're arguing about is what baggage term
"interface" carries with it. I'm neither from a DBC nor Java
background, so to me "interface" just means "how you use the thing"
and it happens to be inherited. I think you're reading more into it
than my deliberately simplistic definition.

The other part that's up in the air is if method signatures will be
enforced on subclasses by default or if you have to turn this feature on.
So far, I'm assuming it won't be enforced by default and using the
"is interface" property to turn it on. Like I said, I could go either way
and the choice of property name just happens to go with what I feel an
interface is.

sch...@pobox.com

unread,
Oct 4, 2002, 7:36:35 PM10/4/02
to Trey Harris, Chris Dutton, Mike Lambert, perl6-l...@perl.org
On Fri, Oct 04, 2002 at 06:26:31PM -0400, Trey Harris wrote:
> > But what does it mean to be "stronger"? How does Eiffel figure out if
> > a given precondition is "stronger" or "weaker" than another?
>
> Like I said before, boolean logic. Preconditions are OR'd together
> (starting with the deepest subclass and working back to the most ancestral
> class, in order to short-circuit most effectively), postconditions are
> AND'd together (in the opposite order, same reason).

I can see too many problems with that technique, I think one was
already mentioned where subclasses can unintentionally weaken
preconditions to the point of eliminating them. I'm sort of casting
about looking for another way.

David Whipp

unread,
Oct 4, 2002, 8:02:57 PM10/4/02
to sch...@pobox.com, Trey Harris, Chris Dutton, Mike Lambert, perl6-l...@perl.org
Michael G Schwern <sch...@pobox.com> wrote:

> I can see too many problems with that technique, I think one was
> already mentioned where subclasses can unintentionally weaken
> preconditions to the point of eliminating them.

Which is, of course, why we OR them, yet AND the postconditions

It is perfectly valid for an implementation to say "I can meet the
post-condition, no matter what input you give me" i.e. it can
eliminate the precondition, but not the postcondition. As code:


class Math is interface {
method sqrt (int $x) {
PRE { $x >= 0 }
POST { sqrt($x) * sqrt($x) == $x }
}
}

class KnowsAboutComplex is Math
{
method sqrt (int $x) {
PRE { TRUE }
# calc result, possibly complex
}
}

Of course, KnowsAboutComplex would be invalid if the
interface had required the result to be a Real.


Dave.

Trey Harris

unread,
Oct 4, 2002, 8:21:55 PM10/4/02
to sch...@pobox.com, Chris Dutton, Mike Lambert, perl6-l...@perl.org
In a message dated Fri, 4 Oct 2002, sch...@pobox.com writes:

> On Fri, Oct 04, 2002 at 06:26:31PM -0400, Trey Harris wrote:
> > > But what does it mean to be "stronger"? How does Eiffel figure out if
> > > a given precondition is "stronger" or "weaker" than another?
> >
> > Like I said before, boolean logic. Preconditions are OR'd together
> > (starting with the deepest subclass and working back to the most ancestral
> > class, in order to short-circuit most effectively), postconditions are
> > AND'd together (in the opposite order, same reason).
>
> I can see too many problems with that technique, I think one was
> already mentioned where subclasses can unintentionally weaken
> preconditions to the point of eliminating them. I'm sort of casting
> about looking for another way.

Could you illustrate a case? I don't know what you're talking about.
It's completely valid to eliminate a precondition, because "true" is the
weakest possible precondition.

By definition, an assertion P is weaker than another assertion Q iff Q
implies P. Requiring a computer to determine if some condition A,
expressed in arbitrary computer code, is weaker than some condition B,
also expressed in arbitrary computer code, is unsolvable in the general
case and equivalent to the halting problem.

So, you either abandon the general case and incorporate a theorem prover
into the compiler (!) or you make use of the following theorem: (P or Q)
is weaker than Q, because Q implies (P or Q).

Trey


Michael G Schwern

unread,
Oct 4, 2002, 9:48:21 PM10/4/02
to Trey Harris, Chris Dutton, Mike Lambert, perl6-l...@perl.org
On Fri, Oct 04, 2002 at 08:21:55PM -0400, Trey Harris wrote:
> > I can see too many problems with that technique, I think one was
> > already mentioned where subclasses can unintentionally weaken
> > preconditions to the point of eliminating them. I'm sort of casting
> > about looking for another way.
>
> Could you illustrate a case? I don't know what you're talking about.
> It's completely valid to eliminate a precondition, because "true" is the
> weakest possible precondition.

I thought someone had posted an example, but now I can't find it and I can't
remember what it was.


--

Michael G. Schwern <sch...@pobox.com> http://www.pobox.com/~schwern/


Perl Quality Assurance <per...@perl.org> Kwalitee Is Job One

It sure is fun masturbating.
http://www.unamerican.com/

Michael Lazzaro

unread,
Oct 4, 2002, 11:01:30 PM10/4/02
to sch...@pobox.com, perl6-l...@perl.org

Thanks, if it's looking like lvalues are really out I'll edit that draft
to take out the lvalue stuff and do it the other way. (And if Damian's
happy with slots, that probably means we can get a lot of the other
attribute recipies out of the way pretty quick. Huzzah!)

I had mixed feelings about defining and using a term like "slots" in a
draft that could mutate into a faq/tutorial, and went back and forth on
it (haven't done Self in years, and never in a non-academic setting.)
Think, think... Well, no, screw it: the best philosophy is to present
and (re)define the terms ourselves, as many as we need, but perhaps with
a footnote on language of origin. We don't want to invent new
terminology, we want to reuse it. Duh. :-P

If no objections, we'll use the term "slots" to mean the aforementioned
attribute/method symmetry. I'll edit the text to give a proposed perl6
"glossary" definition.

MikeL

Chris Dutton

unread,
Oct 4, 2002, 11:36:20 PM10/4/02
to sch...@pobox.com, Mike Lambert, perl6-l...@perl.org

On Friday, October 4, 2002, at 06:23 PM, sch...@pobox.com wrote:

> On Fri, Oct 04, 2002 at 09:13:45AM -0400, Chris Dutton wrote:
>>> How exactly does one "weaken" a precondition?
>>
>> At least in Eiffel, if you redefine a method, you may not give it
>> stringer preconditions than the original method, but you may have
>> stronger postconditions. In essence, you're not requiring any more of
>> the client, but you can ensure more to them on completion, thus
>> maintaining the parent's contract.
>
> But what does it mean to be "stronger"? How does Eiffel figure out if
> a given precondition is "stronger" or "weaker" than another?

Perhaps an example is the best way to demonstrate this:

class FOO
creation make
feature
make(input: SOME_OTHER_CLASS) is
require
input /= Void
do
-- something here
ensure
input /= Void
end
end

-- Good:

class BAR
inherit FOO redefine make end
creation make
feature
make(input: SOME_OTHER_CLASS) is
-- no requirements, weaker precondition
do
-- yada yada
ensure
input /= Void
old input.some_attribute /= input.some_attribute
-- stronger postcondition is ok.
end
end

-- Bad:

class BAR
inherit FOO redefine make end
creation make
feature
make(input: SOME_OTHER_CLASS) is
require
input /= Void
input.some_attribute = 1
-- requiring more than the parent's make procedure is bad.
do
-- yada yada
-- Not ensuring anything to the client is bad.
-- The parent honored that in its contract, so
-- the child must also.
end
end

Allison Randal

unread,
Oct 5, 2002, 1:48:21 PM10/5/02
to Trey Harris, perl6-l...@perl.org
On Fri, Oct 04, 2002 at 12:03:44AM -0400, Trey Harris wrote:
> In a message dated Thu, 3 Oct 2002, John Williams writes:
>
> > On Thu, 3 Oct 2002, Trey Harris wrote:
> >
> > > Incidentally, has there been any headway made on how you DO access
> > > multiple classes with the same name, since Larry has (indirectly) promised
> > > us that? I.e., I import two classes "LinkedList" and "BTree", both of
> > > which define a "Node" class?
> >
> > Hopefully, LinkedList defines a LinkedList::Node class, and BTree defines
> > a BTree::Node class. Either by explicitly naming them that or by virtue
> > of being defined as an "inner" class (which might also make it private).
>
> Ah, but that's the way you do it now--name the classes differently.
> (Easy--assuming you control the source code!) In Perl 6, we're supposed
> to be able to use multiple versions of the same class concurrently, which
> I think would imply also being able to use multiple classes that happened
> to be named the same thing.

It doesn't imply that. The currently proposed solution is that the true
name of a class will include at least the version. But, you can alias
classes just like variables:

# compile time
class Foo is really (Acme::Kung::Foo-1_54);

# runtime
class Foo := Acme::Kung::Foo-1_54;

# (the full classname format hasn't been hashed out yet, this is
# just for sake of illustration)

So, you could reuse the same short name for multiple different classes,
as long as you lexically scoped your aliases. I wouldn't recommend it
though, unless you're trying to confuse people. Even in the rare case
when you need to use two different versions of the same class in the
same code, there will be a clearer way to do it.

More useful: keep a site-wide or company-wide file of version aliases to
make sure everyone uses the same version, and to make upgrades to the
next version as simple as editing a single file.

Allison

Trey Harris

unread,
Oct 5, 2002, 2:50:11 PM10/5/02
to Allison Randal, perl6-l...@perl.org
In a message dated Sat, 5 Oct 2002, Allison Randal writes:
> More useful: keep a site-wide or company-wide file of version aliases to
> make sure everyone uses the same version, and to make upgrades to the
> next version as simple as editing a single file.

Ah, but the usual case is this:

You download from CPAN class A that depends on version 1.0 of class N.
You then download class B that also depends on version 1.0 of class N.
You create an application that uses both classes A and B (and thus N
through the dependencies.) Some time later, you discover a bug that
requires you to upgrade class B, but the upgrade now depends on class 1.1
of class N. Class A hasn't been upgraded yet, and turns out not to work
well with version 1.1 of N. So you need both versions 1.1 and 1.0 of
class N running in the application--preferably without having to modify
any of your app, class A, or class B.

This could be made to work (assuming that classes A and B both specify
which version of N they need).

Trey

Allison Randal

unread,
Oct 5, 2002, 6:51:04 PM10/5/02
to Trey Harris, perl6-l...@perl.org
On Sat, Oct 05, 2002 at 02:50:11PM -0400, Trey Harris wrote:
>
> Ah, but the usual case is this:
>
> You download from CPAN class A that depends on version 1.0 of class N.
> You then download class B that also depends on version 1.0 of class N.
> You create an application that uses both classes A and B (and thus N
> through the dependencies.) Some time later, you discover a bug that
> requires you to upgrade class B, but the upgrade now depends on class 1.1
> of class N. Class A hasn't been upgraded yet, and turns out not to work
> well with version 1.1 of N. So you need both versions 1.1 and 1.0 of
> class N running in the application--preferably without having to modify
> any of your app, class A, or class B.
>
> This could be made to work (assuming that classes A and B both specify
> which version of N they need).

Aye, that's the case it was designed to fix. The others are just extras.

class A would have:

use Acme::N-1_0; # or whatever the format of the name is

while the updated class B would have:

use Acme::N-1_1;

The two versions can co-exist because they have different names.

Allison

Chromatic

unread,
Oct 7, 2002, 8:56:19 PM10/7/02
to perl6-l...@perl.org

Assuming that A and B do not both explicity specify which version they need, it
would then seem a SMOP to hijack use() to use the correct version of the module for
each class. Correct?

-- c

Allison Randal

unread,
Oct 8, 2002, 4:30:05 PM10/8/02
to chromatic, perl6-l...@perl.org

Hmmm... I can see how it might be handy if C<use Acme::N;> would just
grab the highest numbered "Acme::N..." module on the system. It sounds
like you want something more configurable than that, though.

Allison

Trey Harris

unread,
Oct 8, 2002, 4:32:40 PM10/8/02
to Allison Randal, chromatic, perl6-l...@perl.org
In a message dated Tue, 8 Oct 2002, Allison Randal writes:
> Hmmm... I can see how it might be handy if C<use Acme::N;> would just
> grab the highest numbered "Acme::N..." module on the system.

After a

no strict 'versions';

please. :-)

Trey

Allison Randal

unread,
Oct 8, 2002, 6:16:27 PM10/8/02
to Trey Harris, perl6-l...@perl.org

That would make me a little more comfortable with having a versioning
system that can be ignored at will. I'm all for making code loudly say
"I'm turning off a useful safety feature!"

We're at least feinting at the problem.

Allison

Larry Wall

unread,
Oct 11, 2002, 9:00:28 PM10/11/02
to Garrett Goebel, Michael G Schwern, perl6-l...@perl.org, du...@pobox.com, Michael Lazzaro, Allison Randal
On Fri, 4 Oct 2002, Garrett Goebel wrote:
: That wasn't the way I remembered it from Apoc 4... The following example is

: not in A4, but its what I inferred from it...
:
: Class Foo {
: method eat($food) is abstract {
: PRE { ... }
: POST { ... }
: }
: }

A4 was proposing those for a different purpose, and confusing the issue with DBC.
Those are now FIRST and LAST, and the pre/post syntax is still undecided.

Larry

Larry Wall

unread,
Oct 11, 2002, 8:50:55 PM10/11/02
to Allison Randal, Trey Harris, perl6-l...@perl.org
On Sat, 5 Oct 2002, Allison Randal wrote:
: use Acme::N-1_0; # or whatever the format of the name is

I don't see why it couldn't just be:

use Acme::1.0;

After all, we don't have package names starting with numbers right now...

Larry

Larry Wall

unread,
Oct 11, 2002, 9:07:37 PM10/11/02
to John Williams, Trey Harris, perl6-l...@perl.org
On Thu, 3 Oct 2002, John Williams wrote:

: On Thu, 3 Oct 2002, Trey Harris wrote:
:
: > Incidentally, has there been any headway made on how you DO access
: > multiple classes with the same name, since Larry has (indirectly) promised
: > us that? I.e., I import two classes "LinkedList" and "BTree", both of
: > which define a "Node" class?
:
: Hopefully, LinkedList defines a LinkedList::Node class, and BTree defines
: a BTree::Node class. Either by explicitly naming them that or by virtue
: of being defined as an "inner" class (which might also make it private).

A private inner class:

my class Node {...}

A public inner class:

our class Node {...}

That last one actually declares a subclass of the current class, just as

our $foo;

puts $foo into the current package.

Larry

Larry Wall

unread,
Oct 11, 2002, 9:24:16 PM10/11/02
to Michael G Schwern, du...@pobox.com, Michael Lazzaro, Allison Randal, perl6-l...@perl.org
On Thu, 3 Oct 2002, Michael G Schwern wrote:
: On Thu, Oct 03, 2002 at 05:23:08PM -0500, Jonathan Scott Duff wrote:
: > I don't know, but I think it's supposed to be like this:
: >
: > # part of the signature
: > method turn($dir,$ang) is pre { $ang <= 20 } {
: > ...
: > }
: >
: > # part of the implementation
: > method turn($dir,$ang) {
: > PRE { $ang <= 20 }
: > ...
: > }
: >
: > turn() methods of derived classes would inherit the precondition in the
: > first case but not the second. I don't know why you'd want to do this
: > exactly, but it seems to me that perl should allow it.
:
: I see us already smashing too many things into the method signature as it

: is. It will rapidly get messy if you have a method with a complex signature
: and a handful of attributes and preconditions.
:
: Also, where do the postconditions go? In the signature at the front? That

: doesn't make sense, it should go at the end so you can keep them in mind
: when you're writing the return code.
:
: Consider...
:
: method foo($this, $that) is memoized is something
: is pre { $this <= 42 }
: is pre { $that == $this / 2 }
: is pre { a lot of code which is hard to
: shove into a block of code
: this close to the right margin }
: is post { what is a post condition
: doing at the front? }
: {
: ...
: }
:
: They can, of course, be pulled back from the margin:
:
: method foo($this, $that) is memoized is something
: is pre { $this <= 42 }
: is pre { $that == $this / 2 }
: is pre { now we have a little bit more room to play with using
: a differnt indentation style }
: is post { but post conditions are still distanced from the
: code which return()s }
: {
: ...
: }
:
: I realize that conditions are technically part of the signature, but putting
: them in there paints us into a stylistic corner.

Hmm. It sounds like a cry for help. :-)

method foo($this, $that) is memoized is something

{
...
}

# Additionaly...
also &foo


is pre { $this <= 42 }
is pre { $that == $this / 2 }
is pre { now we have a little bit more room to play with using
a differnt indentation style }
is post { but post conditions are still distanced from the

code which return()s };

One is tempted to make it:

also note that &foo is pre { ... }

It might be possible to allow "is" after the {...} block, much like an C<else> block.
But an "also" would let us defer all the extras to the end of the class definition.

: I'm also not fond of the pre/PRE distinction. Few of the other special


: blocks (given, eval, try, invar, etc...) use all cap names. At least I hope
: not.

All caps indicates a BEGIN-like block that is not evaluated inline, but
sets a property in the surrounding scope. It's a useful distinction.

: Simply attaching an "is private" attribute to a pre condition block


: seems the simplest way to go about it.

Except that you'd have to parenthesize it:

is pre ({...} is private)

Otherwise it'd merely privatize whatever the first "is" is "issing".

: Just like any other private thing,


: it's not inherited and not visible outside the current class. "pre" vs
: "PRE" doesn't convey that meaning.

Well, yes it does, because the pre is in the declaration, and the
PRE is embedded in the implementation, albeit known at compile time.
Not that we're necessarily going to have PRE/POST blocks anyway,
but that's how they'd parse.

I think it'd be kinda strange (but possible (but possibly useless))
to have a declaration like:

sub foo {
...
PRE { @_ > 0 }
}

That is, the precondition would go away as soon as you redefined the {...}.

Larry

Larry Wall

unread,
Oct 11, 2002, 9:04:11 PM10/11/02
to Peter Haworth, Michael G Schwern, du...@pobox.com, Michael Lazzaro, Allison Randal, perl6-l...@perl.org
On Fri, 4 Oct 2002, Peter Haworth wrote:
: This is the one nice thing about the Pascal-like syntax of Eiffel. It allows
: this situation to be unambiguous and sensibly ordered (as well as giving each
: condition labels, so that violations can be better reported):
:
: foo(this: ThisType, that: ThatType): FooType IS
: REQUIRE
: small: this <= 42
: half: that = this / 2
: DO
: -- implementation goes here
: ENSURE
: fooed_ok: RESULT = baz(this) + that
: END
:
: If you're declaring an abstract feature, just replace the whole DO clause with
: "DEFERRED".

That is exactly what a literal C< {...} > means in Perl 6, and why it's required on forward declarations of
anything that takes a block, if you really mean it that way. You can't say

sub foo;

in Perl 6. You have to say

sub foo {...}

: Also notice how Eiffel's syntax also somehow makes statement
: terminators completely optional.

Yes, well, let's not go there... :-)

: Aren't sub declarations in Perl 6 all expressions? Why couldn't we put the
: post condition at the end, then?
:
: sub foo($this, $that) is memoized is something


: is pre{ $this <= 42 }
: is pre{ $that == $this / 2 }

: {
: # implementation goes here
: } is post{
: # postcondition 1
: } is post{
: # postcondition 2
: }
:
: If you want an abstract method, just omit the implementation block.

The absence of something is hard to notice. Put {...} for an abstract method.

Larry

Luke Palmer

unread,
Oct 11, 2002, 9:45:36 PM10/11/02
to la...@wall.org, a...@ajs.com, pe...@jall.org, perl6-l...@perl.org
> sub f(int $a is constrained($a>=1,"must be positive),
> documented("an integer")) {
> ...
> }
>

I now realize I'm a little fuzzy on the yada-yada-yada operator. What
exactly is it... or what does it do? Is it a statement, an
expression? Could you say things like:

foo(...);

(Admittedly I have no idea what that would mean) Is it just something
that does nothing?

sub f() {
print "Don't see me\n";
}
sub f() {
# do other stuff
}
f;

Would do the same as using ... in the former? I hope not (though I
suppose that's what Perl 5 does). Is it more special than that?

Luke

Larry Wall

unread,
Oct 11, 2002, 9:31:10 PM10/11/02
to Aaron Sherman, Mike Lambert, Perl6 Language List
On 4 Oct 2002, Aaron Sherman wrote:
: There are a very large number of good things that I think we should put
: into properties for meta-programming purposes (e.g. constraints,
: assertions, optimization hints, documentation, etc).
:
: For example:
:
: sub f(int $a is constrained($a>=1,"must be positive),
: documented("an integer"))
: is constrained(some_global_condition),
: documented("applies transformation f to an integer") {
: ...
: }

Another good reason to allow:

sub f(int $a is constrained($a>=1,"must be positive),
documented("an integer")) {
...
}

also &f is constrained(some_global_condition),
documented("applies transformation f to an integer");

or possibly even

sub f(int $a) {
also $a is constrained($a>=1,"must be positive),
documented("an integer");
...
}

also &f is constrained(some_global_condition),
documented("applies transformation f to an integer");

One could argue that, given that "is" is always compile-time, the "also"
is redundant.

sub f(int $a) {


$a is constrained($a>=1,"must be positive),

documented("an integer");
...
}

&f is constrained(some_global_condition),
documented("applies transformation f to an integer");


But maybe that's too weird.

Larry

Trey Harris

unread,
Oct 11, 2002, 9:56:59 PM10/11/02
to Larry Wall, John Williams, perl6-l...@perl.org
In a message dated Fri, 11 Oct 2002, Larry Wall writes:
> A public inner class:
>
> our class Node {...}
>
> That last one actually declares a subclass of the current class, just as
>
> our $foo;
>
> puts $foo into the current package.

When you say "subclass", do you mean "below the current class in the
naming heirarchy", i.e.

class BTree;
our class Node {...}

would create BTree::Node? Or do you really mean *subclass*, i.e., "our
class" causes Node to inherit from BTree? I hope it's the former, but the
word "subclass" does usually imply inheritance....

Trey

Larry Wall

unread,
Oct 11, 2002, 10:12:18 PM10/11/02
to Trey Harris, John Williams, perl6-l...@perl.org
On Fri, 11 Oct 2002, Trey Harris wrote:
: When you say "subclass", do you mean "below the current class in the

: naming heirarchy", i.e.
:
: class BTree;
: our class Node {...}
:
: would create BTree::Node? Or do you really mean *subclass*, i.e., "our
: class" causes Node to inherit from BTree? I hope it's the former, but the
: word "subclass" does usually imply inheritance....

Sorry, I meant a class named within the current package, not a derived class.

Larry

Larry Wall

unread,
Oct 11, 2002, 10:30:15 PM10/11/02
to Trey Harris, Allison Randal, Michael G Schwern, perl6-l...@perl.org
On Thu, 3 Oct 2002, Trey Harris wrote:
: In a message dated Thu, 3 Oct 2002, Allison Randal writes:
: > So far, classes are uppercase and properties are lowercase, but that's
: > convention, not law.
:
: Do runtime (value) properties and compile-time (variable) properties share
: the same namespace?

In general, no.

: That is, to go back to an earlier discussion, if there is a system-defined
: value property C<true> which marks a value as true in boolean contexts,
: can I also define a compile-time property C<true> that makes the variable
: evaluate as true, whatever its value?

No, I think the boolean test would probably ignore the variable at that point.
Think of variable properties as more of a "tie". The variable could contrive
to always return a true value, but that's about it. There's unlikely to be
any implicit relationship between variable properties and value properties.

A major exception to that might be that the type declared on the variable
is checked against the value's type at appropriate times.

Larry

Larry Wall

unread,
Oct 11, 2002, 10:22:05 PM10/11/02
to Luke Palmer, a...@ajs.com, pe...@jall.org, perl6-l...@perl.org
On Fri, 11 Oct 2002, Luke Palmer wrote:
: I now realize I'm a little fuzzy on the yada-yada-yada operator. What

: exactly is it... or what does it do? Is it a statement, an
: expression?

It's a term.

: Could you say things like:
:
: foo(...);

Yes.

: (Admittedly I have no idea what that would mean) Is it just something
: that does nothing?

Nope, it issues a warning (or maybe an exception) if you try to execute it.
It's basically for stubbing things out when you're doing rapid prototyping,
but that's kind of what is happening with forward declarations as well.

: sub f() {


: print "Don't see me\n";
: }
: sub f() {
: # do other stuff
: }
: f;
:
: Would do the same as using ... in the former? I hope not (though I
: suppose that's what Perl 5 does). Is it more special than that?

Well, redefining a function with {...} certainly shouldn't produce a
warning about redefinition. Other than that, it should act similarly.

I was only half joking when I said we might have !!! and ??? as well.
Maybe ??? never complains and !!! always throws an exception. Except
then everyone will be declaring their functions using !!! instead of ... .
Maybe !!! is the "okay" one, and ??? is warns, and ... is fatal.
But it seems mnemonic to identify !!! with $!, and ??? with something
that is questionable. That would make ... a no-op.

But maybe we just stick with ... and make its behavior pragmatically
controllable.

Larry

Graham Barr

unread,
Oct 12, 2002, 4:33:20 AM10/12/02
to Larry Wall, Allison Randal, Trey Harris, perl6-l...@perl.org
On Fri, Oct 11, 2002 at 05:50:55PM -0700, Larry Wall wrote:
> On Sat, 5 Oct 2002, Allison Randal wrote:
> : use Acme::N-1_0; # or whatever the format of the name is
>
> I don't see why it couldn't just be:
>
> use Acme::1.0;

I agree thats better. But why not separate the version more by using
a different separator than :: between the module name and the version.
Or even something like

use Acme[1.0];

> After all, we don't have package names starting with numbers right now...

Er, we do.

http://search.cpan.org?perldoc?Pod::Simple::31337

It would seem that (currently) only the top-level namespace may not start
with a number.

But I would also not that CPAN only has 3 such modules, all by the same author
and all ::31337

Graham.

Iain Spoon Truskett

unread,
Oct 12, 2002, 12:08:27 AM10/12/02
to perl6-l...@perl.org
* Larry Wall (la...@wall.org) [12 Oct 2002 10:51]:

[...]
> use Acme::1.0;

> After all, we don't have package names starting with numbers right now...

Well, there's than Pod::Simple::31337, which confused search.cpan.org for a
bit. But none which _start_ with a number, no.


cheers,
--
Iain.

Larry Wall

unread,
Oct 12, 2002, 11:43:46 AM10/12/02
to Graham Barr, Allison Randal, Trey Harris, perl6-l...@perl.org
On Sat, 12 Oct 2002, Graham Barr wrote:
: Or even something like
:
: use Acme[1.0];

Hmm. Looks kinda like a subscript, which could be sliced to give an
acceptable version range:

use Acme[1;0..];

Except slices aren't powerful enough to say what you really want to say:

use Acme[1;17.. | 2;0..];

Er, or maybe they are now...

The precedence is screwed up though. It'd have to be

use Acme[ (1;17..) | (2;0..) ];

If we use | and & as sugar for any() and all(), then their precedence
should probably be the same as || and &&. But that still doesn't
help for superposed slices or lists, since commas and semicolons are
lower precedence yet. I'm afraid any() and all() don't help either.

Please don't anyone suggest special low-precedence versions...

Larry

Chromatic

unread,
Oct 12, 2002, 12:21:48 PM10/12/02
to perl6-l...@perl.org
On Sat, 12 Oct 2002 08:43:46 -0700, Larry Wall wrote:

> On Sat, 12 Oct 2002, Graham Barr wrote:
> : Or even something like
> :
> : use Acme[1.0];
>
> Hmm. Looks kinda like a subscript, which could be sliced to give an
> acceptable version range:
>
> use Acme[1;0..];

Might it be possible to say "use any installed version of Acme below 2.0"?

use Acme[..2;0];

That could also be helpful.

-- c

Larry Wall

unread,
Oct 12, 2002, 12:51:15 PM10/12/02
to Graham Barr, Allison Randal, Trey Harris, perl6-l...@perl.org
On Sat, 12 Oct 2002, Larry Wall wrote:
: The precedence is screwed up though. It'd have to be

:
: use Acme[ (1;17..) | (2;0..) ];

Or maybe this:

use Acme[1;17..] |
Acme[2;0..];

That doesn't, of course, express any preference for one version over another,
since | logically happens in parallel universes, in constant time. It also
doesn't let you pass different arguments to different versions. It does, however,
let you try using differently named modules that provide the same interface:

use Acle[1;17..] |
Acme[1;13..] |
Acne[1;14..];

That syntax doesn't, however, let you alias the interface to a single name.
Hmm.

class MyAc is really(Acle[1;17..] | Acme[1;13..] | Acne[1;14..]);
use MyAc 1,2,3;

Seems a little odd to do the "use" on the alias, but it seems like it could
work. I'm not quite sure when a class wave function collapses though...

Larry

Luke Palmer

unread,
Oct 12, 2002, 1:10:24 PM10/12/02
to la...@wall.org, gb...@pobox.com, a...@shadowed.net, tr...@sage.org, perl6-l...@perl.org
> Date: Sat, 12 Oct 2002 08:43:46 -0700 (PDT)
> From: Larry Wall <la...@wall.org>

>
> If we use | and & as sugar for any() and all(), then their precedence
> should probably be the same as || and &&.

Should they? I had in mind something just above comparisons. That
way:

if $x == 3 || $y == 4 {...}

and

if $x == 1 | 2 { ... }

both DWIM. Is there a case for not doing this?

Luke

Larry Wall

unread,
Oct 12, 2002, 1:37:52 PM10/12/02
to Luke Palmer, gb...@pobox.com, a...@shadowed.net, tr...@sage.org, perl6-l...@perl.org
On Sat, 12 Oct 2002, Luke Palmer wrote:
: > Date: Sat, 12 Oct 2002 08:43:46 -0700 (PDT)

Mmm, only a precedence simplification case. I'd forgotten about
the comparison ops. Right above them is probably a good place.

Larry

Larry Wall

unread,
Oct 12, 2002, 2:58:46 PM10/12/02
to Michael Lazzaro, sch...@pobox.com, perl6-l...@perl.org
On Fri, 4 Oct 2002, Michael Lazzaro wrote:
: Thanks, if it's looking like lvalues are really out I'll edit that draft
: to take out the lvalue stuff and do it the other way.

No, lvalue methods are definitely in, and pretty much always have been.
(There will be no problem with post-processing the value, as the next
Apocalypse will make clear.)

: (And if Damian's
: happy with slots, that probably means we can get a lot of the other
: attribute recipies out of the way pretty quick. Huzzah!)
:
: I had mixed feelings about defining and using a term like "slots" in a
: draft that could mutate into a faq/tutorial, and went back and forth on
: it (haven't done Self in years, and never in a non-academic setting.)
: Think, think... Well, no, screw it: the best philosophy is to present
: and (re)define the terms ourselves, as many as we need, but perhaps with
: a footnote on language of origin. We don't want to invent new
: terminology, we want to reuse it. Duh. :-P
:
: If no objections, we'll use the term "slots" to mean the aforementioned
: attribute/method symmetry. I'll edit the text to give a proposed perl6
: "glossary" definition.

"Slots" isn't quite right. Inside the class we distinguish attributes from
methods. It's only outside the class that they're all methods.

Larry

Chris Dutton

unread,
Oct 12, 2002, 2:50:47 PM10/12/02
to perl6-l...@perl.org

Just a thought, but don't we already have this with the "smart match"
operator?

if $x =~ (1, 2) { ... }

Or would & and | be a bit more strict in use, and thus easier for the
compiler to optimize? For instance, would we be able to:

if $x == 1 | "hello" { ... }

or would both operands have to be of the same type?

Larry Wall

unread,
Oct 12, 2002, 3:38:20 PM10/12/02
to Chris Dutton, perl6-l...@perl.org
On Sat, 12 Oct 2002, Chris Dutton wrote:

: On Saturday, October 12, 2002, at 01:10 PM, Luke Palmer wrote:
:
: >> Date: Sat, 12 Oct 2002 08:43:46 -0700 (PDT)
: >> From: Larry Wall <la...@wall.org>
: >>
: >> If we use | and & as sugar for any() and all(), then their precedence
: >> should probably be the same as || and &&.
: >
: > Should they? I had in mind something just above comparisons. That
: > way:
: >
: > if $x == 3 || $y == 4 {...}
: >
: > and
: >
: > if $x == 1 | 2 { ... }
: >
: > both DWIM. Is there a case for not doing this?
:
: Just a thought, but don't we already have this with the "smart match"
: operator?
:
: if $x =~ (1, 2) { ... }

Yes, =~ implies an any() around a list. But | could leave out the parens,
presuming the precedence is higher than =~.

: Or would & and | be a bit more strict in use, and thus easier for the

: compiler to optimize? For instance, would we be able to:
:
: if $x == 1 | "hello" { ... }
:
: or would both operands have to be of the same type?

I don't see why they'd have to be the same type. There could well be
good reasons for superposing objects of different types.

Larry

0 new messages