Re: txt vs OO [was: Re: Proposal to make class method non-inheritable]

2005-10-26 Thread Michele Dondi

On Tue, 25 Oct 2005, Larry Wall wrote:


But we're trying to design the OO features (indeed, all of Perl 6)
such that you can usefully cargo cult those aspects that are of
immediate interest without being forced to learn the whole thing.
It's not the number one design goal, but it's right up there.


So you're talking about a positive, tame form of cargo cult, giving the 
latter a good name...



Michele
--
you need a brain hack. or a brain of any sort. try a nematode first. the
small incremental improvement won't be such a shock. then you can
graduate to segmented worm brains.
- Uri Guttman in clpmisc, Array Sort Using Regex Matching Fails


Re: txt vs OO [was: Re: Proposal to make class method non-inheritable]

2005-10-26 Thread Larry Wall
On Wed, Oct 26, 2005 at 09:36:48AM +0200, Michele Dondi wrote:
: On Tue, 25 Oct 2005, Larry Wall wrote:
: 
: But we're trying to design the OO features (indeed, all of Perl 6)
: such that you can usefully cargo cult those aspects that are of
: immediate interest without being forced to learn the whole thing.
: It's not the number one design goal, but it's right up there.
: 
: So you're talking about a positive, tame form of cargo cult, giving the 
: latter a good name...

Yes, I hack on more languages than just Perl.  :-)

I use the term cargo cult for lack of a better term, and when I do
so I tend to use it as a verb rather than a noun.  By cargo culting
I mean the process by which most of us learn to use new technology.
We appropriate inappropriately; we have to start using a thing wrongly
before we can start using it rightly.  When we're very young, we learn
by picking up objects and stuffing them into our mouths.  That's not
the appropriate way for an adult to treat most objects, but it's the
right way for a toddler to treat an object, and it's the parents'
responsibility to child-proof the room so the child doesn't chew
on power cords and such.  So another way to say what I said is that
we're trying to make Perl 6 relatively safe for people who are just
starting to use bits of it inappropriately in order to learn it.

The term cargo cult also has some religious connotations, and to a
small extent I mean those too.  The religious wars fought in computer
communities often arise among those with the least understanding of the
deep issues.  People much more easily fall into tribal behavior than
into philosophical behavior.  A deep understanding of bikesheds is that
they're meant to hold bicycles, and it doesn't really matter what color
they are.  But when you first discover a bikeshed, you might mistake
it for a tribal monument of some sort.  It's obviously more important
than the bicycle; after all, it's bigger.  And we might attract more
new husbands or wives from other tribes if we paint it attractively.
So we spend a lot of time painting the outside while the bicycle is
inside rusting.  And the bicycle is what's important, because we should
be reaching out to other tribes, not waiting for them to come to us.

Well, hey, my metaphor is probably painted the wrong color.  But maybe
it's only by using analogies inappropriately that we can begin to
understand how to use them appropriately.

Larry


Re: txt vs OO [was: Re: Proposal to make class method non-inheritable]

2005-10-26 Thread Andrew Savige
--- Larry Wall wrote:
 On Tue, Oct 25, 2005 at 05:24:52PM +0200, Michele Dondi wrote:
 : But maybe that's just me. Whatever, I guess that the {casual,average} 
 : programmer may be scared by its richness and complexity.
 
 But we're trying to design the OO features (indeed, all of Perl 6)
 such that you can usefully cargo cult those aspects that are of
 immediate interest without being forced to learn the whole thing.
 It's not the number one design goal, but it's right up there.

Interesting. I just finished reading Stroustrup's thoughts on evolution
and language design at:

  http://www.research.att.com/~bs/rules.pdf

and noticed he is similarly concerned about making his language easier
for the casual/novice programmer:

  If you are a physicist needing to do a few calculations a week,
   an expert in some business processes involving software, or a
   student learning to program, you want to learn only as many
   language facilities as you need to get your job done.

He also argues in favour of general features over specialized ones:

  C++0x will not be a Windows language or a Web Language ... 

which reminded me of people characterizing Perl as a text processing
language or a CGI language.

Just as Perl 5 evolved Perl 4 from a scripting/text processing language
to a general purpose one (with CPAN modules filling many specialized
niches), Perl 6 seems to be evolving still further down that path,
being applicable to more and varied domains than Perl 5 was.

/-\


Send instant messages to your online friends http://au.messenger.yahoo.com 


txt vs OO [was: Re: Proposal to make class method non-inheritable]

2005-10-25 Thread Michele Dondi

On Fri, 14 Oct 2005, Stevan Little wrote:

I think Perl 6's OO system has the potential to be to OO programming what 
Perl 5, etc was to text processing. This, I believe, is in large part due to


Sorry for replying so late. Thought it seems appropriate to post this in 
this time of Perl 6 fears and rants threads...


Well, the point is that it is interesting to note that text processing 
is an _application area_, whereas OO programming is a programming 
language paradigm.


Despite the intro above, this is not meant to be a rant or to express a 
fear. But it is intended to raise a meditation.


After all, being known for text processing capabilities may be somewhat 
restictive and not faithful of Perl's (including Perl 5) full 
potentiality, but OO programming is somewhat immaterial either, the 
only relevance being the suitability for big projects management.



Michele
--
Ira Kane: If I was a giant nasty alien bird in a department store, where
would I be?
Harry Block: Lingerie.
Ira Kane: Not you, the bird.
Harry Block: Lingerie.
- Evolution, Ivan Reitman


Re: txt vs OO [was: Re: Proposal to make class method non-inheritable]

2005-10-25 Thread Stevan Little


On Oct 25, 2005, at 6:31 AM, Michele Dondi wrote:

On Fri, 14 Oct 2005, Stevan Little wrote:
I think Perl 6's OO system has the potential to be to OO  
programming what Perl 5, etc was to text processing. This, I  
believe, is in large part due to


Sorry for replying so late. Thought it seems appropriate to post  
this in this time of Perl 6 fears and rants threads...


Well, the point is that it is interesting to note that text  
processing is an _application area_, whereas OO programming is a  
programming language paradigm.


Allow me to clarify.

Perl 5 (and below) are known by outsiders (non-perl users) as being a  
really good language for processing text. Ask any friend you know who  
has had little or no exposure to Perl and they will probably tell you  
this. Of course they will also tell you that it is all line noise,  
etc, etc etc. This is the most common perception of Perl by those  
people who have (for the most part) never encountered it.


I think that Perl 6 may become like that for OO. When people who have  
never used or encountered Perl 6 talk about it, they will say, I've  
never used it, but I hear it has lots of really cool OO features.  
Just as now they the same thing re: text-processing.


Sure, this means nothing to people who are actually using it, but  
this is mostly about outside perception. These kinds of things are  
sometimes what will bring people to the language initially, so they  
are not to be taken lightly.


Despite the intro above, this is not meant to be a rant or to  
express a fear. But it is intended to raise a meditation.


After all, being known for text processing capabilities may be  
somewhat restictive and not faithful of Perl's (including Perl 5)  
full potentiality,


Of course not, Perl is also used for CGI, but you can do that better  
with Java now (which is a real language cause it's compiled)


;)

People who are not familiar with a language tend to rely heavily on  
the common knowledge about that language. And also tend to hold  
tightly to the myths and pseudo-facts surrounding their own  
languages. The combination of these two things tends to lead to silly  
statements like the one above.


but OO programming is somewhat immaterial either, the only  
relevance being the suitability for big projects management.


The idea that OO is only relevant for big projects is just as silly  
as saying that Perl is only good for text processing.


Sure I would not use OO to write a small utility script, but the  
modules I access in the script would probably be written using OO.  
And those may be very small modules too, but their re-usability is  
greatly enhanced by various OO features (encapsulation, ability to  
compose-into or use within another class, etc etc etc). This kind of  
thing (IMHO) is why so many people are being drawn to Python and  
Ruby. Hopefully Perl 6 can draw them back.


Stevan









Re: txt vs OO [was: Re: Proposal to make class method non-inheritable]

2005-10-25 Thread Michele Dondi

On Tue, 25 Oct 2005, Stevan Little wrote:

 Well, the point is that it is interesting to note that text processing 
 is an _application area_, whereas OO programming is a programming 
 language paradigm.


Allow me to clarify.

Perl 5 (and below) are known by outsiders (non-perl users) as being a really 
good language for processing text. Ask any friend you know who has had little 
or no exposure to Perl and they will probably tell you this. Of course they 
will also tell you that it is all line noise, etc, etc etc. This is the most 
common perception of Perl by those people who have (for the most part) never 
encountered it.


ack!

I think that Perl 6 may become like that for OO. When people who have never 
used or encountered Perl 6 talk about it, they will say, I've never used it, 
but I hear it has lots of really cool OO features. Just as now they the same 
thing re: text-processing.


I see your point. And I admit I slightly misunderstood you. In any case 
people who don't know Perl and think it's great for text processing may be 
eventually become interested in it if they will have to do... ehm... text 
processing.


But even if Perl will gain a name for it's cool OO features, will it 
become an actual interest for someone if he/she has to do... OO stuff?!? 
The basic idea being that one is attracted by a language or another if its 
features are well suited for some specific application he/she has in mind. 
Not for its features as an abstract thing.


Also, Perl6 OO capabilities are already above the top of my head. But 
maybe that's just me. Whatever, I guess that the {casual,average} 
programmer may be scared by its richness and complexity.


 After all, being known for text processing capabilities may be somewhat 
 restictive and not faithful of Perl's (including Perl 5) full 
 potentiality,


Of course not, Perl is also used for CGI, but you can do that better with 
Java now (which is a real language cause it's compiled)


Of Perl is IMHO even _too_ known for CGI.

 but OO programming is somewhat immaterial either, the only relevance 
 being the suitability for big projects management.


The idea that OO is only relevant for big projects is just as silly as saying 
that Perl is only good for text processing.


ack. I was oversimplifying.

Sure I would not use OO to write a small utility script, but the modules I 
access in the script would probably be written using OO. And those may be 
very small modules too, but their re-usability is greatly enhanced by various 
OO features (encapsulation, ability to compose-into or use within another 
class, etc etc etc). This kind of thing (IMHO) is why so many people are 
being drawn to Python and Ruby. Hopefully Perl 6 can draw them back.


Also, some methods will be very handy even for non-patently-OO blocks, 
e.g. the .pos() one which will replace the somewhat ad hoc pos() function 
or the .subst() one (or whatever it is called, I can't remember exactly) 
which hopefully will get rid of the why doesn't s/// work inside a map() 
question...



Michele
--
Have you ever stopped to consider that what is crashing
your Perl is sitting between the keyboard and chair?
- Sherm Pendley in clpmisc, Re: Perl IDE (edited)


Re: Proposal to make class method non-inheritable

2005-10-14 Thread Piers Cawley
Stevan Little [EMAIL PROTECTED] writes:

 Piers,

 On Oct 12, 2005, at 5:22 AM, Piers Cawley wrote:
 We definitely have two instances of A since, B.isa(::A). We also have
 a fragile implementation of count.

 :)

 Sorry, I purposefully made it a kludge as that is usually the way the  example
 is shown in most tutorials about class methods.

So, let me see if I have this straight here. You're arguing that, because
people are often foolish, we should make it harder to be clever? And you're
using a deliberately broken example as grist to your mill?

Doesn't sound all that Perlish to me.

-- 
Piers Cawley [EMAIL PROTECTED]
http://www.bofh.org.uk/


Re: Proposal to make class method non-inheritable

2005-10-14 Thread Stevan Little

Piers,

On Oct 14, 2005, at 12:14 PM, Piers Cawley wrote:

Stevan Little [EMAIL PROTECTED] writes:

On Oct 12, 2005, at 5:22 AM, Piers Cawley wrote:
We definitely have two instances of A since, B.isa(::A). We also  
have

a fragile implementation of count.



:)

Sorry, I purposefully made it a kludge as that is usually the way  
the  example

is shown in most tutorials about class methods.


So, let me see if I have this straight here. You're arguing that,  
because

people are often foolish, we should make it harder to be clever?


No, more that people have been lead down the wrong paths all too  
often based on limitations of language implementation. And that Perl  
6 should be moving to correct this problem. Sure that might be un- 
Perlish in the sense that we are not leaving every way to do it  
open. But at some point I think you need to shake off the old  
accumulated crud and start fresh, even if that new way might go  
contrary to what some people have been conditioned to think.


I also do not believe that I am making it harder, as much as I am  
making it different. Change is hard, but it *is* inevitable.


I think Perl 6's OO system has the potential to be to OO programming  
what Perl 5, etc was to text processing. This, I believe, is in large  
part due to the fact that Perl 5 had such a slim object system, and  
Larry intended (based on what I have read in A12) to start fresh from  
the ground up. That, coupled with Perl's tendency to borrow the  
best from everywhere, and you have the potential for a really great  
OO system.



And you're using a deliberately broken example as grist to your mill?


The example is the canonical example for class methods/attributes,  
and yes it is broken. However, it's broken-ness only serves to  
illustrate, what I think is, the misunderstanding of the usefulness  
of class methods in general. One only needs to take a quick sampling  
of some of the more popular CPAN modules which sport an OO  
interface to see that all to often class methods are (ab)used to get  
what amounts to procedural modules with inheritence.



Doesn't sound all that Perlish to me.


Perl is many different things to different people, this is part of  
it's beauty as a language. Perl also has the unique ability to be  
able to re-invent itself on a regular basis (shell-scripts, CGI,  
bioinformatics, what next??). I personally think that the definition  
of what is Perlish and what is not Perlish is not only highly  
subjective, but ever changing.


So I guess what I am saying here is thank you, as I will take that  
as a compliment ;)


Stevan




Re: Proposal to make class method non-inheritable

2005-10-13 Thread TSa

HaloO,

Stevan Little wrote:

On Oct 11, 2005, at 8:47 PM, Larry Wall wrote:

You seem to be arguing that a class has no state, but my view is that,
in the abstract, a class encompasses the state of *all* its objects.
It just hasn't picked one particular object to be at the moment.


I love this notion because that makes the type that the class represents
the potential state it would reach when *all* distinguishable instances
were realized---which needs a lot of memory for many classes. But the
bit class/type e.g. has exactly two distinguishable states! Well and
more then these two will never be needed if the algebraic, boolean type
is build with !,  and ||. Negation just exchanges the half of the
type that is in use, the former one is returned into potentiality,
that is, it leaves the programs actuality. The binary connectives leave
false and true in the program respectively as soon as both booleans have
entered the program! That is (1  0 == 0) and (0 || 1 == 1) dual each
other, just as the unrealized potential state of a class duals the actually
realized state of the instances of the class in any particular moment.

Here's a nice magic square picture of the idea:

 -Class .. ::Classmeta space
**
|   /|
|  / |The diagonal line splits the potential(-) from
| /  |the actual(+) instances. Undef and the ::Class
|/   |are the singularities of the class. The state
|   /|of the class moves up the diagonal through instance
|  / |creation, while the GC moves it towards Undef.
| /  |
**
 Undef  .. +Classvalue space

No, not that class has no state, but that with the currently specced  
classes we have inherited behaviors (class methods) but they do not  
inherit the accompanying state (class attributes) as well. I see this  
as potentially very problematic.


What do you mean with not inheriting class state? I would think that
beeing an instance of a class, an object should have access to the shared
class data, but it is not part of the per object state. Or do you mean
that class data is not accessable to the instances at all? I would hope
that this is 'hidden' in the scopes where the class's parts are defined
but of course accessable lexically from class support code there.
--


Re: Proposal to make class method non-inheritable

2005-10-13 Thread Stevan Little


On Oct 13, 2005, at 4:45 PM, TSa wrote:
No, not that class has no state, but that with the currently  
specced  classes we have inherited behaviors (class methods) but  
they do not  inherit the accompanying state (class attributes) as  
well. I see this  as potentially very problematic.




What do you mean with not inheriting class state? I would think that
beeing an instance of a class, an object should have access to the  
shared

class data, but it is not part of the per object state. Or do you mean
that class data is not accessable to the instances at all? I would  
hope
that this is 'hidden' in the scopes where the class's parts are  
defined

but of course accessable lexically from class support code there.


I mean that classes do not inherit class state along subclass lines.  
Take this code for instance:


  class Foo {
  has $.bar;
  }

every instance of Foo I create has it's own copy of $.bar. Now I  
subclass it:


  class Bar is Foo {}

every instance of Bar has it's own copy of $.bar as well. Now look at  
this from the class attribute perspective.


  class Foo {
  our $.baz; # class data here,.. not instance data
  }

Foo has a single copy of $.baz in it's internal namespace. Now  
subclass it:


  class Bar is Foo {}

Bar does not have it own copy of $.baz, in fact Bar's ability to  
access Foo::{$.baz} (or however it would be spelt) is not more  
special than any other class in the system.


The point I am trying to make is that class data is unique to the  
class itself, and subclasses of said class do not have any special  
priviledges or access to that data (leaving auto-generated accessors  
out of the picture for now).


This is different though from how class methods behave, which seems  
to me to be problematic.


Stevan



RE: Proposal to make class method non-inheritable

2005-10-12 Thread Gordon Henriksen
On Tue, Oct 11, 2005 at 06:10:41PM -0400, Stevan Little wrote:

 I would like to propose that class methods do not get inherited along  
 normal class lines.

You mean, make them *not methods?* Because it's not a method unless it
has an invocant, as far as I'm concerned. (Method implies polymorphism.)


: Let's start by making a very basic definition of an *object*,  
: ignoring any implementation details or specifics.
: 
:   object == state + behavior

I don't see how this is a bad thing. Classes don't have state. That's
their lot in life. Que sera! Inheritance of behavior alone is useful.

My primary want for class methods, as a whole, is to provide this sort
of interface in Objective-C:

@interface Host : NSObject {
- (Class)plugInClass;
- (void)setPlugInClass:(Class) plugInClass;
}

@interface PlugIn : NSObject {
- (BOOL)initWithHost:(Host *)host;
+ (BOOL)supportsFeatureA;
+ (BOOL)supportsFeatureB;
}

... later ...
if ([[host plugInClass] supportsFeatureA]) {
... expose UI element ...
}

Rather than having to make plugin creation cheap so that I can do this:

class Host {
public Type PlugInClass {
get { ... }
set { ... }
}
}

class PlugIn {
public bool Host { get; }
public abstract bool SupportsFeatureB { get; }
public abstract bool SupportsFeatureA { get; }
}

... later ...
PlugIn plugIn = (PlugIn) Activator.CreateInstance(host.PlugInClass);
if (plugIn.SupportsFeatureA) {
... expose UI element ...
}

Another alternative is to introduce a PlugInFactory. Which might be
better in complex scenarios. But it's often overkill. And it's certainly
more typing.

In C#, I might also use attributes to decorate the plugin Type. But
those, too, are more typing than class methods (and also weakly typed).

Also, of course, inheriting constructors is nice. Of course, it opens up
the whole designated constructor can of worms. But that's okay; if
you're subclassing, it's your responsibility to make it work

-- 
 
Gordon Henriksen
[EMAIL PROTECTED]



Re: Proposal to make class method non-inheritable

2005-10-12 Thread Piers Cawley
Stevan Little [EMAIL PROTECTED] writes:

 Hello all.

 I would like to propose that class methods do not get inherited along
 normal class lines.

 I think that inheriting class methods will, in many cases, not DWIM.
 This is largely because your are inheriting behavior, and not state
 (since class attributes are not inheritable). Let me explain in more
 detail.

 Let's start by making a very basic definition of an *object*,
 ignoring any implementation details or specifics.

object == state + behavior

 This statement assumes that *objects* at their core are a unique
 state coupled with a collection of behaviors to act upon that
 particular state. Of course we are ignoring all the other class/meta/
 inheritence junk for now.

 To take away the behavior, and only be left with state would degrade
 our object to the level of C struct or Pascal-style record-type. To
 take away the state, and only be left with behavior, would basically
 leave a module/package or some pseudo-random collection of functions.

 So at this point, I think it is safe to say that an *object* should
 have both state and behavior.

 Now, back down from the theoretical cloud to reality. I would like to
 show some canonical class-method examples (and in some cases, show
 how they are broken), then show how they might be better accomplished
 in Perl 6 without the need for class methods to be inherited.

 == Instance Counting Class

 The most common example given for class methods is an instance
 counter. Here is how one might (naively) look in Perl 6:

 class A {
  our $.count;
  method count (Class $c:) { $.count; }
  submethod BUILD {
  $.count++;
  }
 }

 Each time an instance of A is created the counter is incremented. So
 that ...

 A.count; # 0
 A.new;
 A.count; # 1

 Now this makes sense, until we subclass A.

 class B is A {}

 A.count; # still 1
 B.new; # calls A::BUILD

 A.count; # 2
 B.count; # 2

 Clearly, we only have one instance of A, and one instance of B, so
 those numbers are wrong. It could be argued that since B is a subtype
 of A, we do have two A's, but the argument does not work in reverse.
 But either way, I would argue that the results shown above are
 misleading, and probably not what the programmer intended.

We definitely have two instances of A since, B.isa(::A). We also have
a fragile implementation of count.

  class A {
our %.count_of

method count (Class $c:) { %.count_of{$c} }

method BUILD {
  $class = ($?SELF.class)

  @countable_ancestors = $class.ancestors.uniq.grep :{.isa(::A)}

  for $class, [EMAIL PROTECTED] - $c { %.count_of{$c}++ }
}

Where we're assuming I've got the syntax of 'for' right, and that
'ancestors' is a class method that returns all of a class's
ancestors. This might not work too well in the face of a dynamic
inheritance tree, but it should be possible to work around. Something
like this might work:

   Class A {
 our %.instance_count_of

 method count (Class $c: ?$with_descendents = undef) {
   my @interesting_classes = $c;
   if $with_descendents {
 push @interesting_classes, *($c.all_subclasses);
   }
   [+] %.instance_count_of(@interesting_classes)
 }

 method BUILD {
   %.instance_count_of($?SELF.class)
 }
   }

Where we're assuming that a class can find all its subclasses 

-- 
Piers Cawley [EMAIL PROTECTED]
http://www.bofh.org.uk/


Re: Proposal to make class method non-inheritable

2005-10-12 Thread Stevan Little

Gordon,

On Oct 11, 2005, at 9:10 PM, Gordon Henriksen wrote:

On Tue, Oct 11, 2005 at 06:10:41PM -0400, Stevan Little wrote:

I would like to propose that class methods do not get inherited along
normal class lines.


You mean, make them *not methods?* Because it's not a method unless it
has an invocant, as far as I'm concerned. (Method implies  
polymorphism.)


No, they would still have an invocant. That invocant would be an anon- 
class which itself is an instance of Class. It works like so:


(First, lets make a legend)

  -- is instance of
  .. is subclass of

NOTE: Class means the class named Class, this distinction is  
important.


When you create the class Foo, this is what you have:

  Class
^
|
   Foo

Foo is an instance of class Class (Class itself is an instance of  
class Class too, but thats only slightly relevant here).


When you add a class method (one which cannot be inherited), it is  
done with an eigenclass. This changes the above structure into this:


  Class
^
:
  eFoo
^
|
   Foo

Now, we have created an anon-class (or eigenclass), whose entire  
purpose is to hold the class methods of Foo. Since the eigenclass is  
a subclass of Class, then all of Class's methods are inherited. This  
means that our method dispatcher does not need to know about class  
methods as a special case, as far as it is concerned, they are just  
normal instance methods on Foo (which itself is an instance of eFoo,  
which is then a subclass of Class).


Now, why are they not inherited. Lets expand this diagram a little more:

Class
  ^
+-|+
|  |
   Foo...Bar

So Foo and Bar are both instances of Class, and Bar is a subclass of  
Foo. It is fairly straightforward, but now lets introduce the  
eigenclasses to hold class methods.


Class
  ^
..:.
:  :
  eFooeBar
^  ^
|  |
   Foo...Bar

Now, method dispatch for Foo will go to eFoo (since Foo is an  
instance of eFoo, and method dispatch always starts at the class-of  
the instance), and it will continue up to Class (since Class is the  
superclass of eFoo). The same goes for Bar, first to eBar, then to  
Class. Since eFoo and eBar are not connected, then normal method  
dispatching does not go along those lines.


Now, this is not to say that it cannot be made to do so. A slight  
change to the above diagram allows for inheritence of class methods  
very easily.


  Class
^
:
  eFoo...eBar
^  ^
|  |
   Foo...Bar

Now, method dispatch for Bar will go first to it's class (eBar), then  
to any superclasses (eFoo), and any of their superclasses (Class),  
and so on, and so forth. A better diagram of this can be found here  
(http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel/docs/ 
Method_Dispatch_w_EigenClasses.jpg).




: Let's start by making a very basic definition of an *object*,
: ignoring any implementation details or specifics.
:
:   object == state + behavior

I don't see how this is a bad thing. Classes don't have state. That's
their lot in life. Que sera! Inheritance of behavior alone is useful.


Classes do have state though. They have class attributes:

class Foo {
our $.bar;
my $.baz;
}

that state is just not inherited.

I am not actually arguing that inheritance of just behavior is not  
useful, more that inheritance of behavior *without the accompanying  
state* is not useful, and in many cases wrong.




My primary want for class methods, as a whole, is to provide this sort
of interface in Objective-C:

@interface Host : NSObject {
- (Class)plugInClass;
- (void)setPlugInClass:(Class) plugInClass;
}

@interface PlugIn : NSObject {
- (BOOL)initWithHost:(Host *)host;
+ (BOOL)supportsFeatureA;
+ (BOOL)supportsFeatureB;
}

... later ...
if ([[host plugInClass] supportsFeatureA]) {
... expose UI element ...
}


My Objective-C is very rusty, but let met see if I understand what  
you are doing.


Host has-a Class object, which it uses as a plugInClass. Your PlugIn  
then has class methods (supportsFeatureA, supportsFeatureB) which can  
be used by the Host to query the capabilities of its plugInClass.


This type of thing could be accomplished with Roles.

class Host {
my $.plugInClass;
}

role PlugIn {
method initWithHost (Host $h:) { ... }
}

role SupportsFeatureA {
# yes, this Role has a class method in it, which
# the consuming class will get as a class method
method supportsFeatureA (Class $c:) { bool::true }
}

role SupportsFeatureB {
method supportsFeatureB (Class $c:) { bool::true }
}

class AB {
does PlugIn;
does SupportsFeatureA;
does SupportsFeatureB;
}

One could argue that it is more typing, however, I think that in the  
long run, it will be less typing since you never need to repeat the  
supportsFeatureA or supportsFeatureB method, just consume the  

Re: Proposal to make class method non-inheritable

2005-10-12 Thread Stevan Little

Piers,

On Oct 12, 2005, at 5:22 AM, Piers Cawley wrote:

We definitely have two instances of A since, B.isa(::A). We also have
a fragile implementation of count.


:)

Sorry, I purposefully made it a kludge as that is usually the way the  
example is shown in most tutorials about class methods.




  class A {
our %.count_of

method count (Class $c:) { %.count_of{$c} }

method BUILD {
  $class = ($?SELF.class)

  @countable_ancestors = $class.ancestors.uniq.grep :{.isa(::A)}


You can use the MRO here, which is an already linearized list of the  
inheritance tree (in C3 order) with all duplicates removed.




  for $class, [EMAIL PROTECTED] - $c { %.count_of{$c}++ }
}

Where we're assuming I've got the syntax of 'for' right, and that
'ancestors' is a class method that returns all of a class's
ancestors. This might not work too well in the face of a dynamic
inheritance tree, but it should be possible to work around. Something
like this might work:

   Class A {
 our %.instance_count_of

 method count (Class $c: ?$with_descendents = undef) {
   my @interesting_classes = $c;
   if $with_descendents {
 push @interesting_classes, *($c.all_subclasses);
   }
   [+] %.instance_count_of(@interesting_classes)
 }

 method BUILD {
   %.instance_count_of($?SELF.class)
 }
   }

Where we're assuming that a class can find all its subclasses

--
Piers Cawley [EMAIL PROTECTED]
http://www.bofh.org.uk/






Re: Proposal to make class method non-inheritable

2005-10-12 Thread Stevan Little

Gordon,

It just occurred to me that the system shown below could be re- 
written to do away with class methods entirely.


class Host {
my $.plugInClass;
}

role PlugIn {
method initWithHost (Host $h:) { ... }
}

role FeatureA {}
role FeatureB {}
role FeatureC {}

class AB {
does PlugIn;
does FeatureA;
does FeatureB;
}

class ABC {
does AB;
does FeatureC;
}

Now later on, instead of asking the PlugIn if it supportsFeatureB,  
you can just see if it does the FeatureB role, like this:


if ($host.plugInClass.does('FeatureB')) {
# ... do something with FeatureB
}

This will work with the ABC plugin as well since AB is being treated  
as a role, ABC will actually consume all it's subroles, which means  
that ABC will DWIM too. In fact, we get even more from this system  
since we can check if one plug-in is capable of doing another,  
because this just works


if ($host.plugInClass.does('AB')) {
# ...
}

And since an example is better when it is backed up by working code,  
I coded this up using the current meta-model prototype. You can see  
it here: http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel/t/ 
38_PlugIn_example.t


Stevan




On Oct 12, 2005, at 9:41 AM, Stevan Little wrote:

class Host {
my $.plugInClass;
}

role PlugIn {
method initWithHost (Host $h:) { ... }
}

role SupportsFeatureA {
# yes, this Role has a class method in it, which
# the consuming class will get as a class method
method supportsFeatureA (Class $c:) { bool::true }
}

role SupportsFeatureB {
method supportsFeatureB (Class $c:) { bool::true }
}

class AB {
does PlugIn;
does SupportsFeatureA;
does SupportsFeatureB;
}

role SupportsFeatureC {
method supportsFeatureC (Class $c:) { bool::true }
}

class ABC {
does AB;
does SupportsFeatureC;
}





Re: Proposal to make class method non-inheritable

2005-10-12 Thread Stevan Little

Larry,

On Oct 11, 2005, at 8:47 PM, Larry Wall wrote:

On Tue, Oct 11, 2005 at 06:10:41PM -0400, Stevan Little wrote:
: Hello all.
:
: I would like to propose that class methods do not get inherited  
along

: normal class lines.

I think most class methods should be written as submethods instead.


In which case they would not be inherited then. I (obviously) agree  
with you on that :)



You seem to be arguing that a class has no state, but my view is that,
in the abstract, a class encompasses the state of *all* its objects.
It just hasn't picked one particular object to be at the moment.


No, not that class has no state, but that with the currently specced  
classes we have inherited behaviors (class methods) but they do not  
inherit the accompanying state (class attributes) as well. I see this  
as potentially very problematic.



: == Instance Counting Class
:
: The most common example given for class methods is an instance
: counter. Here is how one might (naively) look in Perl 6:
:
: class A {
: our $.count;
: method count (Class $c:) { $.count; }
: submethod BUILD {
: $.count++;
: }
: }

That's obviously broken--the count accessor should be a submethod  
to be

consistent, unless the explicit intent is that any subclass of A
return the count of A's.  Which, not surprisingly, is exactly what
you get below.  It should probably have been declared:

our $.A_count;

in that case.  And in which case you don't need the explicit accessor,
since one would have been provided because of the dot.  If you don't
want the autoaccessor, don't use the dot.


Yes, this example was purposefully broken, but also copied from  
several tutorial on how to use class methods.




I suppose an argument could be made that autoaccessors for class vars
should be submethods by default.  Or maybe my $.count makes a  
submethod,

while our $.A_count makes a method.


I think that is probably not a bad idea. If we not going to inherit  
the class state, then we should not inherit the class method either.



: Clearly, we only have one instance of A, and one instance of B, so
: those numbers are wrong. It could be argued that since B is a  
subtype
: of A, we do have two A's, but the argument does not work in  
reverse.


Sure it does.  It doesn't matter whether B is a subtype of A or not,
you've given it an interface to code that counts A's.


True, that was probably a bad example (culled from other bad examples).


: But either way, I would argue that the results shown above are
: misleading, and probably not what the programmer intended.

That's certainly possible, but it wouldn't be the first time people
have been surprised that the computer did exactly what they asked it
to...  :-)


Also very true.


: Sure, you could do that, however, it complicates the meta-model
: unnecessarily. It is much easier to accomplish this using a  
subclass

: of Class.
:
: class CountingClass is Class {
: has $.counter;
: method count (CountingClass $c:) { $.counter; }
: method new (CountingClass $c: %params) {
: $.counter++;
: next;
: }
: }
:
: class A meta CountingClass {}
: class B meta CountingClass {}
:
: Now A and B both have their own counters neither of which interfere
: with one another.

Only by forcing people to repeat themselves as a matter of policy.
And policy could just as easily have added our $.count to B.  The
real trick would be to set up A such that you don't have to do  
anything

special in B.  I suppose we could say that, by default, if A isa B,
then A gets also gets whatever metaclass B has, not the standard
metaclass supplied by class.


I considered this as well, it seems to make some sense that the  
metaclass of A is also the metaclass of B if A isa B. This would  
actually simplify a particular edge case with the eigenclasses that  
was problematic.


This diagram assumes we have inheritable class methods, and they are  
implemented using the eigenclasses.


  Class
^
:
  eFoo...eBar
^  ^
|  |
   Foo...Bar

The method dispatch for Bar will go first to it's class (eBar), then  
to any superclasses (eFoo), and any of their superclasses (Class),  
and so on, and so forth. When you introduce a custom metaclass like so:



  Class
^
:
CustomMeta
^
:
  eFoo...eBar
^  ^
|  |
   Foo...Bar

A problem occurs with method dispatch for Bar. First it will go to  
eBar, then to eFoo, then to CustomMeta, then to Class, etc, etc.  
Since Bar was not explicitly created with CustomMeta, this is not  
correct.


However, if the metaclasses act as you describe, this is then does  
exactly what it is supposed to. I think it is a sane approach  
personally.



But these are metaclasses, not classes.  You keep writing the type of
the invocant of class methods as Class, but I don't believe that  
anymore.


Sorry, just following the A12 examples :)


The type of the invocant of a class 

Re: Proposal to make class method non-inheritable

2005-10-12 Thread Stevan Little

Gordon,

On Oct 12, 2005, at 10:48 AM, Gordon Henriksen wrote:
Actually, I wondered why you didn't suggest this earlier. :) I  
figured you were a step ahead of me: What if I want more than a  
boolean out of my class method?


Then you put the class methods back in :)

But then your Objective-C interface would need to change too.  
Although, the more complexity you introduce, the closer you get to  
the point when a Factory pattern is just as viable an approach as  
class methods.


Stevan


On Oct 12, 2005, at 10:27, Stevan Little wrote:

Gordon,

It just occurred to me that the system shown below could be re- 
written to do away with class methods entirely.


class Host {
my $.plugInClass;
}

role PlugIn {
method initWithHost (Host $h:) { ... }
}

role FeatureA {}
role FeatureB {}
role FeatureC {}

class AB {
does PlugIn;
does FeatureA;
does FeatureB;
}

class ABC {
does AB;
does FeatureC;
}

Now later on, instead of asking the PlugIn if it  
supportsFeatureB, you can just see if it does the FeatureB  
role, like this:


if ($host.plugInClass.does('FeatureB')) {
# ... do something with FeatureB
}

This will work with the ABC plugin as well since AB is being  
treated as a role, ABC will actually consume all it's subroles,  
which means that ABC will DWIM too. In fact, we get even more from  
this system since we can check if one plug-in is capable of  
doing another, because this just works


if ($host.plugInClass.does('AB')) {
# ...
}

And since an example is better when it is backed up by working  
code, I coded this up using the current meta-model prototype. You  
can see it here: http://svn.openfoundry.org/pugs/perl5/Perl6- 
MetaModel/t/38_PlugIn_example.t


Stevan




On Oct 12, 2005, at 9:41 AM, Stevan Little wrote:



class Host {
my $.plugInClass;
}

role PlugIn {
method initWithHost (Host $h:) { ... }
}

role SupportsFeatureA {
# yes, this Role has a class method in it, which
# the consuming class will get as a class method
method supportsFeatureA (Class $c:) { bool::true }
}

role SupportsFeatureB {
method supportsFeatureB (Class $c:) { bool::true }
}

class AB {
does PlugIn;
does SupportsFeatureA;
does SupportsFeatureB;
}

role SupportsFeatureC {
method supportsFeatureC (Class $c:) { bool::true }
}

class ABC {
does AB;
does SupportsFeatureC;
}










—

Gordon Henriksen
[EMAIL PROTECTED]








Re: Proposal to make class method non-inheritable

2005-10-12 Thread Stevan Little

Gordon,

On Oct 12, 2005, at 11:04 AM, Gordon Henriksen wrote:

On Oct 12, 2005, at 09:41, Stevan Little wrote:

If you use the BUILD submethod, then you never need to worry about  
a that, everything is initialized for you by BUILDALL. Now, if you  
want to have a constructor which accepts positional arguments  
rather than named pairs (as the default does), then you have a  
valid need to override new. Whether you should force this upon  
all your subclasses is a matter of opinion I think.


For varying definitions of initialized. I never much cared for the  
bare poke stuff straight into my instance variables constructor  
along the lines of:


sub new {
my($class, %ARGS);
return bless \%ARGS, $class;
}


Yes, that is a horrible idiom which I hope will die in Perl 6.

That more or less robs the constructor of the behavior part of  
class = state + behavior. I need an opportunity to establish my  
invariants.


Well that is where BUILD comes in, you can do all sorts of mangling  
of parameters in BUILD so that it does what you want it to, there is  
no real need to put this behavior into new.


Of course, when there is no such behavior, it saves a lot of  
repetitive typing in the class. C# 3 is finally growing a syntax  
that resolves this by having the language do the repetitive typing  
at the call site...


X x = new X{ Y = 1, Z = 2 };

means

X x = new X();
x.Y = 1;
x.Z = 2;

And X doesn't need anything but the default constructor.


Yes, this is exactly what the new - CREATE - BUILDALL - BUILD  
chain is doing too.


Now, this is not to say that it cannot be made to do so. A slight  
change to the above diagram allows for inheritence of class  
methods very easily.


  Class
^
:
  eFoo...eBar
^  ^
|  |
   Foo...Bar

Now, method dispatch for Bar will go first to it's class (eBar),  
then to any superclasses (eFoo), and any of their superclasses  
(Class), and so on, and so forth. A better diagram of this can be  
found here (http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel/ 
docs/Method_Dispatch_w_EigenClasses.jpg).


This is more or less how class methods have to work. I would go a  
bit further, though. Too implement this:


Foo : Object
Foo : Bar

The runtime should use an inheritance tree as such:

Object
Class : Object
Foo : Object
Bar : Foo

_Object : Class
_Class : _Object
_Foo : _Class
_Bar : _Foo

Note that every declared class, including Object and Class  
themselves, have an anonymous Class subclass that precisely  
parallels the declared inheritance chain. (Chicken and egg problem?  
Probably. Object and Class are Special.)


This is pretty much the same thing that I am describing, except that  
I don't think that Class needs an anon-class/eigenclass. All object  
models need a cycle at the top, this keeps the turtles-all-the-way- 
down problem away. The usual place is to put the cycle in Class  
(Class is an instance of Class). If you add that anon-class, you  
break the cycle.


With this implementation, there are three places to put state: In  
MyObject (instance variable), in _MyObject (class instance  
variable), or outside of any instance (class variable). The class  
instance variable is the least useful of the three.


Well, I would argue that class instance variables are very useful,  
since that is where methods and attribute meta-objects are stored.  
But I think users should not have direct access to class instance  
variables. But yes, other than that you are correct.


Note: I don't see much value in invoking class methods through  
instances, since a Foo IS_NOT_A Class. If one wants to save the  
user typing .class when invoking class methods through an instance,


Yes, that is bad, another nasty p5 idiom I hope will go away.


I would tend toward resolving it as such:

class Foo {
class_method int Bar(int i) { return i * i; }
}

-- BECOMES --

# Common interface for Foo's class methods.
interface _IFoo {
method int Bar(int i);
}

# The anonymous Class.
class _Foo extends Class implements _IFoo {
int Bar(int i) { return i * i; }
}

# The visible class.
class Foo implements _IFoo {
# Forwards the call to the Class.
void Bar(...) { return this.Class.Bar(...); }
}


I think we can leave the interface part out, but yes, this is  
basically how the eigenclasses work :)


I'll leave the probably obvious role-based interpretation of this  
to those versed in such. :)


s/interface/role/ and you have the role based version ;)

Stevan






Re: Proposal to make class method non-inheritable

2005-10-12 Thread Gordon Henriksen

On Oct 12, 2005, at 09:41, Stevan Little wrote:

If you use the BUILD submethod, then you never need to worry about  
a that, everything is initialized for you by BUILDALL. Now, if you  
want to have a constructor which accepts positional arguments  
rather than named pairs (as the default does), then you have a  
valid need to override new. Whether you should force this upon all  
your subclasses is a matter of opinion I think.


For varying definitions of initialized. I never much cared for the  
bare poke stuff straight into my instance variables constructor  
along the lines of:


sub new {
my($class, %ARGS);
return bless \%ARGS, $class;
}

That more or less robs the constructor of the behavior part of  
class = state + behavior. I need an opportunity to establish my  
invariants.


Of course, when there is no such behavior, it saves a lot of  
repetitive typing in the class. C# 3 is finally growing a syntax that  
resolves this by having the language do the repetitive typing at the  
call site...


X x = new X{ Y = 1, Z = 2 };

means

X x = new X();
x.Y = 1;
x.Z = 2;

And X doesn't need anything but the default constructor.


Now, this is not to say that it cannot be made to do so. A slight  
change to the above diagram allows for inheritence of class  
methods very easily.


  Class
^
:
  eFoo...eBar
^  ^
|  |
   Foo...Bar

Now, method dispatch for Bar will go first to it's class (eBar),  
then to any superclasses (eFoo), and any of their superclasses  
(Class), and so on, and so forth. A better diagram of this can be  
found here (http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel/ 
docs/Method_Dispatch_w_EigenClasses.jpg).


This is more or less how class methods have to work. I would go a bit  
further, though. Too implement this:


Foo : Object
Foo : Bar

The runtime should use an inheritance tree as such:

Object
Class : Object
Foo : Object
Bar : Foo

_Object : Class
_Class : _Object
_Foo : _Class
_Bar : _Foo

Note that every declared class, including Object and Class  
themselves, have an anonymous Class subclass that precisely parallels  
the declared inheritance chain. (Chicken and egg problem? Probably.  
Object and Class are Special.)



With this implementation, there are three places to put state: In  
MyObject (instance variable), in _MyObject (class instance variable),  
or outside of any instance (class variable). The class instance  
variable is the least useful of the three.



Note: I don't see much value in invoking class methods through  
instances, since a Foo IS_NOT_A Class. If one wants to save the user  
typing .class when invoking class methods through an instance, I  
would tend toward resolving it as such:


class Foo {
class_method int Bar(int i) { return i * i; }
}

-- BECOMES --

# Common interface for Foo's class methods.
interface _IFoo {
method int Bar(int i);
}

# The anonymous Class.
class _Foo extends Class implements _IFoo {
int Bar(int i) { return i * i; }
}

# The visible class.
class Foo implements _IFoo {
# Forwards the call to the Class.
void Bar(...) { return this.Class.Bar(...); }
}

I'll leave the probably obvious role-based interpretation of this to  
those versed in such. :)



And I'm going to shut my yap, now, having butted into the middle of a  
discussion of a hopelessly complex runtime that I haven't been  
following for a 18 months. :)


—

Gordon Henriksen
[EMAIL PROTECTED]




Re: Proposal to make class method non-inheritable

2005-10-12 Thread chromatic
On Wed, 2005-10-12 at 12:00 -0400, Stevan Little wrote:

 Usefulness aside, why do Roles and Classes need to be seperate  
 beasts? In the current meta-model prototype, the role system is laid  
 atop the class system so that the following is true:
 
 Class is an instance of Class
 Role is an instance of Class
 Class does Role
 
 This then means that Role also .does Role since Role is an instance  
 of Class (which does Role).
 
 It gets very cyclical, but it essentially means that all classes can  
 be treated as roles. This allows for all sorts of interesting things  
 to happen actually.

I've always thought that classes were more specific than roles in that
you can't apply a class to another class.  (Maybe that's the wrong
direction of specificity.  Though I am positive that .does() is more
general than .isa(), I always have to stop and think about which
direction co- and contra-variance goes.)

Certainly I think declaring a class should imply a role of the same
name, even if you can't actually apply that role and mix in state and
behavior.

 I have to admit though, that this comes directly from Scala (so maybe  
 we are not alone here out on the edge :)

I've also heard that Sather does something similar but don't know any
details.

-- c



Re: Proposal to make class method non-inheritable

2005-10-12 Thread Gordon Henriksen
Actually, I wondered why you didn't suggest this earlier. :) I  
figured you were a step ahead of me: What if I want more than a  
boolean out of my class method?


On Oct 12, 2005, at 10:27, Stevan Little wrote:


Gordon,

It just occurred to me that the system shown below could be re- 
written to do away with class methods entirely.


class Host {
my $.plugInClass;
}

role PlugIn {
method initWithHost (Host $h:) { ... }
}

role FeatureA {}
role FeatureB {}
role FeatureC {}

class AB {
does PlugIn;
does FeatureA;
does FeatureB;
}

class ABC {
does AB;
does FeatureC;
}

Now later on, instead of asking the PlugIn if it  
supportsFeatureB, you can just see if it does the FeatureB  
role, like this:


if ($host.plugInClass.does('FeatureB')) {
# ... do something with FeatureB
}

This will work with the ABC plugin as well since AB is being  
treated as a role, ABC will actually consume all it's subroles,  
which means that ABC will DWIM too. In fact, we get even more from  
this system since we can check if one plug-in is capable of doing  
another, because this just works


if ($host.plugInClass.does('AB')) {
# ...
}

And since an example is better when it is backed up by working  
code, I coded this up using the current meta-model prototype. You  
can see it here: http://svn.openfoundry.org/pugs/perl5/Perl6- 
MetaModel/t/38_PlugIn_example.t


Stevan




On Oct 12, 2005, at 9:41 AM, Stevan Little wrote:


class Host {
my $.plugInClass;
}

role PlugIn {
method initWithHost (Host $h:) { ... }
}

role SupportsFeatureA {
# yes, this Role has a class method in it, which
# the consuming class will get as a class method
method supportsFeatureA (Class $c:) { bool::true }
}

role SupportsFeatureB {
method supportsFeatureB (Class $c:) { bool::true }
}

class AB {
does PlugIn;
does SupportsFeatureA;
does SupportsFeatureB;
}

role SupportsFeatureC {
method supportsFeatureC (Class $c:) { bool::true }
}

class ABC {
does AB;
does SupportsFeatureC;
}








—

Gordon Henriksen
[EMAIL PROTECTED]




Re: Proposal to make class method non-inheritable

2005-10-12 Thread Brent 'Dax' Royal-Gordon
Stevan Little [EMAIL PROTECTED] wrote:
 I would like to propose that class methods do not get inherited along
 normal class lines.

I think you're not thinking about many major usage cases for class methods.

For one example, look at my Cipher suite.  (It's in Pugs's ext/Cipher
directory.)  The Cipher base class implements most of the visible API,
while subclasses simply override a few internal methods; Cipher turns
the wide-ranging, convenient external API into a smaller, more easily
implementable internal API.

Some of Cipher's methods are class methods, including the
pseudo-procedural .encipher/.decipher and the pseudo-functional
.encipherer/.decipherer methods.  These methods are included
specifically *to* be inherited.

In my opinion, class method inheritance is an important part of
class-based OO--almost as important as object method inheritance. 
Removing features simply because their implementation is inconvenient
is not The Perl Way.  If it were, Perl 6 would be Java With Sigils.

--
Brent 'Dax' Royal-Gordon [EMAIL PROTECTED]
Perl and Parrot hacker


Re: Proposal to make class method non-inheritable

2005-10-12 Thread Rob Kinyon
All -

I'm partly to blame for this thread because I put the idea into
Steve's head that class methods being inheritable may be dogma and not
a useful thing. Mea culpa.

That said, I want to put forward a possible reason why you would
want class methods to be inheritable - to provide pure functions.

If we go back to every function/method/subroutine being behavior,
it's pretty evident that you need some state for that behavior to
operate upon. In a procedural function, the state is provided. In an
object, that state is both provided and inherent in the instance the
method is operating upon. In functional languages, functions maintain
their own state through closures, continuations,  and the like.

I might want to provide in a base class a set of useful sorting
routines or other such items. These would be true procedural functions
and there would be a warning thrown if it accessed class state.

Rob


Re: Proposal to make class method non-inheritable

2005-10-12 Thread Stevan Little

Brent,

On Oct 11, 2005, at 8:17 PM, Brent 'Dax' Royal-Gordon wrote:

Stevan Little [EMAIL PROTECTED] wrote:


I would like to propose that class methods do not get inherited along
normal class lines.



I think you're not thinking about many major usage cases for class  
methods.


Actually I have considered many common usages including those which  
you describe below, and it is my belief that only a few are truly  
valid uses and not abuses of class method functionality. What I kept  
coming back to was that pretty much all the *abuses* of class methods  
were better done in some other way, and that even the *valid* uses  
were nothing more than design choices, and could be accomplished in  
some other manner.



For one example, look at my Cipher suite.  (It's in Pugs's ext/Cipher
directory.)  The Cipher base class implements most of the visible API,
while subclasses simply override a few internal methods; Cipher turns
the wide-ranging, convenient external API into a smaller, more easily
implementable internal API.


Your internal API and your external API have little to do with one  
another as far as I can tell. The external API is simply a set of  
convenience functions which create instances of your classes in  
various ways (very cool ways I might add, especially the functional  
API, very nice stuff). However, you could easily remove external API,  
and your internal API would not really suffer, it would only require  
that the user manually create what your class methods create for you.


While many people think Factories are many times overkill (me among  
them), what you are doing is a perfect candidate for the Factory  
pattern. In fact, one could say you are already doing an ad-hoc  
Factory pattern with your inheritable class methods.



Some of Cipher's methods are class methods, including the
pseudo-procedural .encipher/.decipher and the pseudo-functional
.encipherer/.decipherer methods.  These methods are included
specifically *to* be inherited.


Your documentation says the following things:

  The Cipher API's procedural interface is good enough for many  
purposes.
  Although the interface is said to be procedural, it is invoked via  
two class

  methods.

  The Cipher API is fundamentally object-oriented; the procedural  
and functional

  interfaces are layers on top of the object-oriented backend.

Both indicate to me an acknowledgment that you are knowingly abusing  
the inheritance of class methods to make your functional and  
procedural APIs work. Now, please don't take this as an insult or  
slam of some kind. All good programmers know when to abuse language  
elements to get what they need. However, I am of the opinion that  
maybe we should leave these old idioms/abuses aside.



In my opinion, class method inheritance is an important part of
class-based OO--almost as important as object method inheritance.


I disagree with you on this point (of course, otherwise I would not  
have started this thread), but I will admit that inheritable class  
methods are a very common OO idiom, and that fact (good or bad)  
should be taken into account.



Removing features simply because their implementation is inconvenient
is not The Perl Way.  If it were, Perl 6 would be Java With Sigils.


To be honest, the implementation is not inconvenient at all, in fact  
I have already done it twice (correctly at least, the meta-model  
currently has inheritable class methods, but the implementation is  
crap).


1) A Mini-MetaModel with Eigenclasses

http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel/docs/ 
MiniMetaModel_w_eigenclasses.pl


Whenever I am doing something which has the potential to dig deeply  
into the core of the meta-model, I do it first with a Mini-MetaModel.  
(The MMM (mini-meta-model) is a small self-bootstrapping single- 
inheritance meta-model in under 2-300 LOC and usually which tends to  
be much easier to mess with than the real meta-model.) If you look  
at the new method in Class, you will see it creates an Eigenclass  
for each class (this is where the class methods get stored), then  
adding class methods is accomplished with the add_singleton_method  
method. You will find a number of tests towards the bottom of the  
file which demonstrate the inheritance of the class methods.


2) By using a subclass of Class

http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel/t/ 
37_inherited_class_methods.t


I did this test at autrijus's request, it creates a  
ClassWithInheritedClassMethods class which is a subclass of Class.  
If you create your classes (Foo, Bar, what have you) using  
ClassWithInheritedClassMethods, then you can add class methods,  
again with the add_singleton_method, and they are inherited  
correctly by subclasses.


The code to make ClassWithInheritedClassMethods work is only 10  
lines long, so as you can see the implementation is not difficult or  
inconvenient at all.


To properly implement this in the current meta-model prototype would  

Re: Proposal to make class method non-inheritable

2005-10-11 Thread Damian Conway

Anyway, I have said my peace, what do you all think?


I think there are serious problems with this proposal. For a start, it would 
be very difficult to create *any* objects at all if the Cnew() class method 
wasn't inheritable.


Damian


Re: Proposal to make class method non-inheritable

2005-10-11 Thread Dave Whipp

Stevan Little wrote:
I would like to propose that class methods do not get inherited along  
normal class lines.


One of the things that has annoyed me with Java is that it's class 
methods don't inherit (dispatch polymorphically). This means that you 
can't apply the template method pattern to static (class) methods. I 
hope Perl 6 doesn't copy this feature.


Re: Proposal to make class method non-inheritable

2005-10-11 Thread Stevan Little

David,

On Oct 11, 2005, at 7:49 PM, Dave Whipp wrote:

Stevan Little wrote:

I would like to propose that class methods do not get inherited  
along  normal class lines.


One of the things that has annoyed me with Java is that it's class  
methods don't inherit (dispatch polymorphically). This means that  
you can't apply the template method pattern to static (class)  
methods. I hope Perl 6 doesn't copy this feature.


If you would please give a real-world-useful example of this usage of  
class-methods, I am sure I could show you, what I believe, is a  
better approach that does not use class methods.


As for Java's static methods, they are very different from class  
methods in Perl 6. Java's static methods are little more than  
functions which have access to other static members. This feature  
is available in Perl 5 now in the form of subs in a package namespace  
and package scoped variables. The fact that Java uses the method call  
syntax to access static methods is (IMHO) just an attempt to have  
consistency in calling conventions. I say this because (as you  
pointed out) they share very little with other methods.


Stevan



Re: Proposal to make class method non-inheritable

2005-10-11 Thread Dave Whipp

Stevan Little wrote:

David,

...
If you would please give a real-world-useful example of this usage of  
class-methods, I am sure I could show you, what I believe, is a  better 
approach that does not use class methods.

...

The example I've wanted to code in Java is along the lines of:

public class Base {
  public static main(String[] args) {
 init();
 do_it(args);
 cleanup()
  }
}

and then define a bunch of derived classes as my main class.

public class Derived extends Base {
  static init() { print(doing init); }
  static do_it(String[] args) { print(doing body); }
  static cleanup() { print(doing cleanup); }
}

% javac Derived
% java Derived

In other words, I wanted to not have a main function on the class that I 
run as the application.


This example, of course, doesn't apply to Perl -- but I think that the 
basic pattern is still useful


Re: Proposal to make class method non-inheritable

2005-10-11 Thread Larry Wall
On Tue, Oct 11, 2005 at 06:10:41PM -0400, Stevan Little wrote:
: Hello all.
: 
: I would like to propose that class methods do not get inherited along  
: normal class lines.

I think most class methods should be written as submethods instead.

: I think that inheriting class methods will, in many cases, not DWIM.  
: This is largely because your are inheriting behavior, and not state  
: (since class attributes are not inheritable). Let me explain in more  
: detail.
: 
: Let's start by making a very basic definition of an *object*,  
: ignoring any implementation details or specifics.
: 
:   object == state + behavior
: 
: This statement assumes that *objects* at their core are a unique  
: state coupled with a collection of behaviors to act upon that  
: particular state. Of course we are ignoring all the other class/meta/ 
: inheritence junk for now.
: 
: To take away the behavior, and only be left with state would degrade  
: our object to the level of C struct or Pascal-style record-type. To  
: take away the state, and only be left with behavior, would basically  
: leave a module/package or some pseudo-random collection of functions.
: 
: So at this point, I think it is safe to say that an *object* should  
: have both state and behavior.

You seem to be arguing that a class has no state, but my view is that,
in the abstract, a class encompasses the state of *all* its objects.
It just hasn't picked one particular object to be at the moment.

: Now, back down from the theoretical cloud to reality. I would like to  
: show some canonical class-method examples (and in some cases, show  
: how they are broken), then show how they might be better accomplished  
: in Perl 6 without the need for class methods to be inherited.
: 
: == Instance Counting Class
: 
: The most common example given for class methods is an instance  
: counter. Here is how one might (naively) look in Perl 6:
: 
: class A {
: our $.count;
: method count (Class $c:) { $.count; }
: submethod BUILD {
: $.count++;
: }
: }

That's obviously broken--the count accessor should be a submethod to be
consistent, unless the explicit intent is that any subclass of A
return the count of A's.  Which, not surprisingly, is exactly what
you get below.  It should probably have been declared:

our $.A_count;

in that case.  And in which case you don't need the explicit accessor,
since one would have been provided because of the dot.  If you don't
want the autoaccessor, don't use the dot.

I suppose an argument could be made that autoaccessors for class vars
should be submethods by default.  Or maybe my $.count makes a submethod,
while our $.A_count makes a method.

: Each time an instance of A is created the counter is incremented. So  
: that ...
: 
: A.count; # 0
: A.new;
: A.count; # 1
: 
: Now this makes sense, until we subclass A.
: 
: class B is A {}
: 
: A.count; # still 1
: B.new; # calls A::BUILD
: 
: A.count; # 2
: B.count; # 2
: 
: Clearly, we only have one instance of A, and one instance of B, so  
: those numbers are wrong. It could be argued that since B is a subtype  
: of A, we do have two A's, but the argument does not work in reverse.  

Sure it does.  It doesn't matter whether B is a subtype of A or not,
you've given it an interface to code that counts A's.

: But either way, I would argue that the results shown above are  
: misleading, and probably not what the programmer intended.

That's certainly possible, but it wouldn't be the first time people
have been surprised that the computer did exactly what they asked it
to...  :-)

: What is happening here is that we are inheriting behavior, but not  
: inheriting state. Which goes against the core definition of *objects*.

I'd say that state is precisely what we're inheriting here.  It's just
the state of something that is not the object.  But that was already
true of class A as well.

: I can solve this, just make class attributes inheritable?, you say.

Don't see how that would help, unless you also force every class to
redeclare the attributes.  (By the way, attributes of the form $.count
are already inheritable, being shorthand for $?SELF.count.)

: Sure, you could do that, however, it complicates the meta-model  
: unnecessarily. It is much easier to accomplish this using a subclass  
: of Class.
: 
: class CountingClass is Class {
: has $.counter;
: method count (CountingClass $c:) { $.counter; }
: method new (CountingClass $c: %params) {
: $.counter++;
: next;
: }
: }
: 
: class A meta CountingClass {}
: class B meta CountingClass {}
: 
: Now A and B both have their own counters neither of which interfere  
: with one another.

Only by forcing people to repeat themselves as a matter of policy.
And policy could just as easily have added our $.count to B.  The
real trick would be to set up A such that you don't have to do anything
special in B.  I suppose we could say that, by default, if A isa B,
then A gets also 

Re: Proposal to make class method non-inheritable

2005-10-11 Thread Stevan Little

David,

On Oct 11, 2005, at 8:42 PM, Dave Whipp wrote:


Stevan Little wrote:


David,


...
If you would please give a real-world-useful example of this usage  
of  class-methods, I am sure I could show you, what I believe, is  
a  better approach that does not use class methods.



...

The example I've wanted to code in Java is along the lines of:

public class Base {
  public static main(String[] args) {
 init();
 do_it(args);
 cleanup()
  }
}

and then define a bunch of derived classes as my main class.

public class Derived extends Base {
  static init() { print(doing init); }
  static do_it(String[] args) { print(doing body); }
  static cleanup() { print(doing cleanup); }
}

% javac Derived
% java Derived

In other words, I wanted to not have a main function on the class  
that I run as the application.


This example, of course, doesn't apply to Perl -- but I think that  
the basic pattern is still useful


I think this example is constrained by the way Java handles the main  
static method. This same pattern could be done using instance  
methods, and a little bit of reflection in Java.


public interface Base {
public void init;
public void do_it(String[] args);
public void cleanup;
}

public class BaseRunner {
public static main (String[] args) {
ClassLoader cl = new java.lang.ClassLoader();
Class c = cl.findClass(args[0]);
Base b = c.newInstance();
b.init();
b.do_it(args);
b.cleanup();
}
}

public class Derived implements Base {
  public void init() { print(doing init); }
  public void do_it(String[] args) { print(doing body); }
  public void cleanup() { print(doing cleanup); }
}

NOTE: this code is untested :)

This version actually allows you to vary the subclasses though the  
command line arguments, which provides even greater flexibility and  
does not require you to recompile BaseRunner or Base.


Doing something similar in Perl 6 is even easier than the Java version.

Stevan