Re: class interface of roles

2006-10-12 Thread TSa

HaloO,

Jonathan Lang wrote:

Still not following.  Can you give an example?


The example in the original post contains a class GenSquare that
has got an equal method that checks the sides of the self square
and the incoming argument square. The GenPointMixin role provides
an equal method that compares the x and y coordinates. The correct
final method equal of the composed class needs to check sides and
coordinates. If the simple side checking equal of the class
overrides the closure from the role there is a false implementation.
OTOH, forcing all classes to call the role closure is bad design of
the composition process. Hence I'm arguing for a super keyword that
in a role refers to the class. In the example super.equal($p) calls
the side checking closure.



Note that it's entirely possible for attributes to not make it into
the final class, if the accessor methods get redefined in such a way
as to remove reference to the attributes.  This is part of the notion
that roles supply an outline of what the class should do, but only the
class actually supplies the definitive details of how to do it.


I see that you regard the class as the ultimate definer of
functionality. The role requires a method including its signature
but the class implements it. For the type system the role encodes
the guarantee of the method availability.



As I see it: is and does declarations in a role impose
requirements on the final class: it must derive from another class
(is), or it must compose another role (does).  method and has
are each one part requirement and one part suggestion: for method,
the class is required to include a method that matches the given name
(which, of course, includes the method's signature), and a particular
closure is suggested that the class can accept or override.


I almost agree here. The only thing I'm asking for is that the role's
closure is not discarded so easily. The designer of the role takes
responsibility for the role's part in the final method closure. The
combination process should produce the correct result automatically
and independent of the class's cooperation.



Thus, the only things that I'd recommend using to calculate a
type-boundary would be the superclasses (provided by is) and the
method names (provided by method and has).


That makes classes too typeish. The type system is mostly based on
roles. The class inheritance graph should not be used for typing.
Or do you want constraints on the class derivation process that
guarantees subclasses to be subtypes? As I read it the class derivation
is free to violate replaceability of subclasses where superclasses
are expected. Roles are a guarantee of functionality not classes.



I agree with the idea behind the current definition of this: if the
class provides its own definition for a method, that should take
precedence over the role's definition.  If it doesn't, then it adopts
the role's definition as its own.


I would hope it is the role if a as of now
unknown syntax has declared it. Perhaps it should be even the default.
The rational for my claim is that a role is composed several times
and then every class doing the role automatically gets the correct
version. Otherwise all classes are burdened with caring for the role's
part in the method.


Huh?


Yeah! The role adds a certain aspect to the correct implementation of
a method. And so does the class. But it is the role that is composed
into the class not the other way around. A role is intended to be
composed several times into completely different classes. With blind
precedence to class methods the role's aspects are lost and have to
be reintroduced in each and every class. I consider that inconvenient
and error prone.



  It
 should assume that if Foo overrides A's implementation of blah, Foo
 knows what it's doing; by the principle of least surprise, Foo should
  never end up overriding A's implementation of blah only to find that
  the original implementation is still being used by another of the
 methods acquired from A.

Could you make an example because I don't understand what you mean with
original implementation and how that would be used by role methods.


   role A {
 method foo() { say Ah... }
 method bar() { $self.foo() }
   }


Isn't that self.foo() without the sigil? It is clear that .foo
is dispatched on the class.


[..]
   class Baz {
 method foo() {
   $self!'A::foo'();
   say Choo!;
 }
 method bar() { $self.foo() }
 method baz() { $self!'A::foo'() }
 my method 'A::foo'() { say Ah... }
   }


What is A referring to here? Baz doesn't compose role A here.
And why the exclamation mark?



In Baz, Cmy method 'A::foo'() represents the original implementation
of foo(), while Cmethod foo() represents the final implementation
chosen by the class.


OK, thanks for the example.



If you were to allow a role method to directly refer to its own
implementation, you could do something like:

role A {
 method foo() { say Ah... }
 

Re: Runtime role issues

2006-10-12 Thread Miroslav Silovic

Paul Seamons wrote:


On closer inspection, is it even possible to add a Role to a Class at 
runtime?  



If it isn't now, I would certainly like to have a hook available through 
MOP (which is, to the best of my knowledge, still unspecified).




I thought that Class and Role composition outside of compile time 
resulted in

a new pseudo Class for the subsequent instances of that composition - in
which case the original Class would remain unmodified.



I believe 'does' and 'but' operators work that way, yep. Additionally, 
they're per instance. Offhand I don't even recall any way to create an 
uninstantiated class with a role mixed at runtime (would my 
$class_foobar = ::Foo but ::Bar do the trick?)


  Miro



Re: class interface of roles

2006-10-12 Thread Jonathan Lang

TSa wrote:

HaloO,

Jonathan Lang wrote:
 Still not following.  Can you give an example?

The example in the original post contains a class GenSquare that
has got an equal method that checks the sides of the self square
and the incoming argument square. The GenPointMixin role provides
an equal method that compares the x and y coordinates. The correct
final method equal of the composed class needs to check sides and
coordinates.  If the simple side checking equal of the class
overrides the closure from the role there is a false implementation.


Actually, the correct equal method for the composed class needs to
check the sides of the square, because how the class defines it: in
this example, class GenSquare _is_ the final class, and so whatever
method it provides _is_ the final method, for good or ill.  If this
results in other method definitions inherited from GenPointMixin
behaving strangely, then GenSquare needs to override those methods as
well.

Mind you, the above implies a radical shift in the underlying
semantics, akin to having class Dog compose role Tree and redefining
method bark() to suit its own nature.  Proper use of role composition
is to refine the role's underlying concept, not to radically alter it.
Even if we were to go with a modified version of the original
example, where GenSquare is a role and both GenSquare and GenPoint are
being composed into a final class - say, GenPositionedSquare - you
still have the problem that the final class is conceptually supposed
to be both a GenSquare and a GenPoint at the same time.  If the
underlying concepts behind the composed roles are fundamentally
incompatable (such as a Dog and a Tree), you're going to have
problems.


OTOH, forcing all classes to call the role closure is bad design of
the composition process. Hence I'm arguing for a super keyword that
in a role refers to the class. In the example super.equal($p) calls
the side checking closure.


This is what happens by default; no special syntax is needed.


 Note that it's entirely possible for attributes to not make it into
 the final class, if the accessor methods get redefined in such a way
 as to remove reference to the attributes.  This is part of the notion
 that roles supply an outline of what the class should do, but only the
 class actually supplies the definitive details of how to do it.

I see that you regard the class as the ultimate definer of
functionality. The role requires a method including its signature
but the class implements it. For the type system the role encodes
the guarantee of the method availability.


Exactly.


 As I see it: is and does declarations in a role impose
 requirements on the final class: it must derive from another class
 (is), or it must compose another role (does).  method and has
 are each one part requirement and one part suggestion: for method,
 the class is required to include a method that matches the given name
 (which, of course, includes the method's signature), and a particular
 closure is suggested that the class can accept or override.

I almost agree here. The only thing I'm asking for is that the role's
closure is not discarded so easily. The designer of the role takes
responsibility for the role's part in the final method closure. The
combination process should produce the correct result automatically
and independent of the class's cooperation.


Perl has yet to implement a telepathic compiler, so the compiler can
only make best guesses as to what the programmer intended.  For now,
we have to make some concessions to reality; one such concession is
that the most specific thing should have authority over (and
responsibility for) the less specific things.  The thing being
composed into is by definition more specific than the thing being
composed when it comes to implementation; thus, the latter should be
given free rein to redefine the methods provided by the former - and
if things go wrong, you should blame the latter rather than the
former.  Letting a role override a decision made by a class that it's
composed into means that there's something about the role's
implementation that the class cannot touch.


 Thus, the only things that I'd recommend using to calculate a
 type-boundary would be the superclasses (provided by is) and the
 method names (provided by method and has).

That makes classes too typeish. The type system is mostly based on
roles. The class inheritance graph should not be used for typing.


It is a fact that class inheritance affects the behaviour of a class;
it cannot be disregarded when considering type.

That said, class inheritance (with respect to its semantic differences
from role composition) is an area where my understanding is rather
shaky.  To me, the whole notion of inheritance is a bit too typeish
for my tastes; I try to handle _all_ code reuse by means of roles,
with classes only being brought into play when I want to be able to
instantiate an object.  That is, I tend to define what an object is

Re: Runtime role issues

2006-10-12 Thread Jonathan Lang

Miroslav Silovic wrote:

Paul Seamons wrote:

 On closer inspection, is it even possible to add a Role to a Class at
 runtime?


If it isn't now, I would certainly like to have a hook available through
MOP (which is, to the best of my knowledge, still unspecified).


To modify a class at runtime, use Cis also.



 I thought that Class and Role composition outside of compile time
 resulted in
 a new pseudo Class for the subsequent instances of that composition - in
 which case the original Class would remain unmodified.


I believe 'does' and 'but' operators work that way, yep. Additionally,
they're per instance. Offhand I don't even recall any way to create an
uninstantiated class with a role mixed at runtime (would my
$class_foobar = ::Foo but ::Bar do the trick?)


Probably not; but Cmy ::class_foobar := Foo but Bar might.

--
Jonathan Dataweaver Lang


Re: Runtime role issues

2006-10-12 Thread Larry Wall
On Thu, Oct 12, 2006 at 09:27:53AM -0700, Jonathan Lang wrote:
: To modify a class at runtime, use Cis also.

Cis also is compile time.  You'd have to eval it.

Larry


Re: Runtime role issues

2006-10-12 Thread Aaron Sherman

Ovid wrote:


The intermediate class solves the problem but it instantly suggests
that we have a new design pattern we have to remember.  Basically, if
I can't lexically scope the additional behavior a role offers, I
potentially need to remove the role or use the intermediate class
pattern.


my Dog $dog .= new;
my $junkyard = $dog but Guard;

You probably don't need to touch the class, but a particular object. You 
can lexically scope changes to an object using but and my quite easily. 
If you really need a modified class, then I think this would do it, but 
I'm not sure if it works:


my $junkyarddog = class is Dog does Guard {};
my ::($junkyarddog) $spot .= new;


[svn:perl6-synopsis] r13096 - doc/trunk/design/syn

2006-10-12 Thread larry
Author: larry
Date: Thu Oct 12 14:52:22 2006
New Revision: 13096

Modified:
   doc/trunk/design/syn/S01.pod
   doc/trunk/design/syn/S05.pod

Log:
Changed enforced backtracking from + to ! to avoid conflicting with Friedl's ++


Modified: doc/trunk/design/syn/S01.pod
==
--- doc/trunk/design/syn/S01.pod(original)
+++ doc/trunk/design/syn/S01.podThu Oct 12 14:52:22 2006
@@ -89,7 +89,7 @@
 =item *
 
 Perl 6 should be malleable enough that it can evolve into the imaginary
-perfect language, Perl 7.  This darwinian imperative implies support
+perfect language, Perl 7.  This darwinian imperative implies support
 for multiple syntaxes above and multiple platforms below.
 
 =item *

Modified: doc/trunk/design/syn/S05.pod
==
--- doc/trunk/design/syn/S05.pod(original)
+++ doc/trunk/design/syn/S05.podThu Oct 12 14:52:22 2006
@@ -14,9 +14,9 @@
Maintainer: Patrick Michaud [EMAIL PROTECTED] and
Larry Wall [EMAIL PROTECTED]
Date: 24 Jun 2002
-   Last Modified: 9 Oct 2006
+   Last Modified: 12 Oct 2006
Number: 5
-   Version: 38
+   Version: 39
 
 This document summarizes Apocalypse 5, which is about the new regex
 syntax.  We now try to call them Iregex rather than regular
@@ -1230,9 +1230,9 @@
 never backtrack in a Ctoken unless some outer regex has specified a
 C:panic option that applies.  If you want to prevent even that, use
 C*:, C+:, or C?: to prevent any backtracking into the quantifier.
-If you want to explicitly backtrack, append either a C? or a C+
+If you want to explicitly backtrack, append either a C? or a C!
 to the quantifier.   The C? forces minimal matching as usual,
-while the C+ forces greedy matching.  The Ctoken declarator is
+while the C! forces greedy matching.  The Ctoken declarator is
 really just short for
 
 regex :ratchet { ... }
@@ -1279,16 +1279,16 @@
 
 =item *
 
-To force the preceding atom to do greedy backtracking,
-append a C:+ or C+ to the atom.  If the preceding token
-is a quantifier, the C: may be omitted.  (Perl 5 has no
-corresponding construct because backtracking always defaults
-to greedy in Perl 5.)
+To force the preceding atom to do greedy backtracking in a
+spot that would default otherwise, append a C:! to the atom.
+If the preceding token is a quantifier, the C: may be omitted.
+(Perl 5 has no corresponding construct because backtracking always
+defaults to greedy in Perl 5.)
 
 =item *
 
 To force the preceding atom to do no backtracking, use a single C:
-without a subsequent C? or C+.
+without a subsequent C? or C!.
 Backtracking over a single colon causes the regex engine not to retry
 the preceding atom:
 
@@ -1316,7 +1316,7 @@
 an alternation, so you may also need to put C: after it if you
 also want to disable that.  If an explicit or implicit C:ratchet
 has disabled backtracking by supplying an implicit C:, you need to
-put an explicit C:+ after the alternation to enable backing into
+put an explicit C! after the alternation to enable backing into
 another alternative if the first pick fails.
 
 =item *


Re: Synposis 26 - Documentation [alpha draft]

2006-10-12 Thread Tim Bunce
On Thu, Oct 12, 2006 at 02:55:57PM +1000, Damian Conway wrote:
 Dave Whipp wrote:
 
 I'm not a great fan of this concept of reservation when there is no 
 mechanism for its enforcement (and this is perl...).
 
 What makes you assume there will be no mechanism for enforcement? The 
 standard Pod parser (of which I have a 95% complete Perl 5 implementation) 
 will complain bitterly--as in cyanide--when unknown pure-upper or 
 pure-lower block names are used.

That's going to cause pain when people using older parsers try to read
docs written for newer ones. Would a loud warning plus some best-efforts
fail-safe parsing be possible?

Tim.

 The whole point of reserving these namespaces is not to prevent users from 
 misusing them, but to ensure that when we eventually get around to using a 
 particular block name, and those same users start screaming about it, we 
 can mournfully point to the passage in the original spec and silently shake 
 our heads. ;-)
 
 Damian


Synposis 26 - Documentation [alpha draft]

2006-10-12 Thread Jonathan Lang

Tim Bunce wrote:

Damian Conway wrote:
 Dave Whipp wrote:
 I'm not a great fan of this concept of reservation when there is no
 mechanism for its enforcement (and this is perl...).

 What makes you assume there will be no mechanism for enforcement? The
 standard Pod parser (of which I have a 95% complete Perl 5 implementation)
 will complain bitterly--as in cyanide--when unknown pure-upper or
 pure-lower block names are used.

That's going to cause pain when people using older parsers try to read
docs written for newer ones.


If I understand you correctly, the pain to which you're referring
would come from the possibility of a name that's reserved by the newer
version of Pod, but not by the older version.  Wouldn't the simplest
solution be to let a Pod document announce its own version, much like
Perl can?

--
Jonathan Dataweaver Lang


Re: Synposis 26 - Documentation [alpha draft]

2006-10-12 Thread Tim Bunce
On Thu, Oct 12, 2006 at 03:57:01PM -0700, Jonathan Lang wrote:
 Tim Bunce wrote:
 Damian Conway wrote:
  Dave Whipp wrote:
  I'm not a great fan of this concept of reservation when there is no
  mechanism for its enforcement (and this is perl...).
 
  What makes you assume there will be no mechanism for enforcement? The
  standard Pod parser (of which I have a 95% complete Perl 5 
 implementation)
  will complain bitterly--as in cyanide--when unknown pure-upper or
  pure-lower block names are used.
 
 That's going to cause pain when people using older parsers try to read
 docs written for newer ones.
 
 If I understand you correctly, the pain to which you're referring
 would come from the possibility of a name that's reserved by the newer
 version of Pod, but not by the older version.

Yes.

 Wouldn't the simplest solution be to let a Pod document announce its
 own version, much like Perl can?

How would that actually help? The old parser still wouldn't know what
new keywords have been added or how to parse them.

Tim.