Re: Re: class interface of roles

2006-10-07 Thread Stevan Little

On 10/6/06, TSa [EMAIL PROTECTED] wrote:

HaloO,

Stevan Little wrote:
 As for how the example in the OP might work, I would suspect that
 super would not be what we are looking for here, but instead a
 variant of next METHOD.

I'm not familiar with the next METHOD syntax. How does one get the
return value from it and how are parameters passed? Would the respective
line in the equal method then read:

return next METHOD($p) and self.x == $p.x and self.y == $p.y;

I think that a super keyword might be nice syntactic sugar for this.


I think super is not something we would want in Roles, it implies
ordering, which defeats the flattening aspect of Roles. IIRC the
syntax to call the next method with new args and a return value is
this:

 return call($p) and self.x == $p.x and self.y == $p.y;

However, I am not sure I really like the look of that myself.



  However, even with that an ordering of some
  kind is implied

The only ordering I see is that the class is up from the role's
perspective.


But thats the whole problem, there is no up in roles, they are flattened.


When more then one role is combined and all require
the presence of an equal method I think the roles can be combined
in any order and the super refers to the class combined so far.
IOW, at any given time in the composition process there is a current
version of the class' method. The final outcome is a method WALK
or however this is called in composition order. Conceptually this
is method combination: seen from outside the class has just one
type correct method equal. Theoretical background can be found in
http://www.jot.fm/issues/issue_2004_01/column4


I do not think method combination should be the default for role
composition, it would defeat the composeability of roles because you
would never have conflicts.

However, I can see the possibility of method combinations in roles
being some kind of special case. How that might look from a syntactic
perspective I have no idea.


 I suppose this is again where the different concepts of classes are
 roles can get very sticky. I have always look at roles, once composed
 into the class, as no longer needing to exist. In fact, if it weren't
 for the idea of runtime role compostion and runtime role
 introspection, I would say that roles themselves could be garbage
 collected at the end of the compile time cycle.

I see that quite different: roles are the primary carrier of type
information!


Well yes, they do seem to have taken on this role ;). However, roles
as originally envisioned in the Traits paper are not related to the
type system, but instead related to class/object system. In fact the
Trait paper gave it's examples in Smalltalk, which is not a strongly
typed language (unless you count the idea that *everything* is an
object and therefore that is their type).

I think we need to be careful in how we associate roles with the type
system and how we assocaite them with the object system. I worry that
they will end up with conflicting needs and responsibilities and roles
will end up being too complex to be truely useful.


Dispatch depends on a partial ordering of roles.


Type based dispatch does (MMD), but class based method dispatch
doesn't need it at all.

The whole fact that dispatching requires roles to be partially ordered
actually tells me that maybe roles should not be so hinged to the type
system since roles are meant to be unordered.

Possiblely we should be seeing roles as a way of *implementing* the
types, and not as a core component of the type system itself?

I did some experimentation with this in Moose::Autobox, but that is
for Perl 5 so I am not sure how relevant it is here.

- Stevan


Re: Re: class interface of roles

2006-10-07 Thread Stevan Little

On 10/6/06, TSa [EMAIL PROTECTED] wrote:

HaloO,

Stevan Little wrote:
 On 10/2/06, Jonathan Lang [EMAIL PROTECTED] wrote:
 This notion of exclusionary roles is an interesting one, though.  I'd
 like to hear about what kinds of situations would find this notion
 useful; but for the moment, I'll take your word that such situations
 exist and go from there.

 Well to be honest, I haven't found a real-world usage for it yet (at
 least in my travels so far), but the Fortress example was this:

  trait OrganicMolecule extends Molecule
  excludes { InorganicMolecule }
  end
  trait InorganicMolecule extends Molecule end

Wouldn't that be written in Perl6 the other way around?

   role OrganicMolecule {...}
   role InorganicMolecule {...}

   role Molecule does OrganicMolecule ^ InorganicMolecule {...}

Which is a nice usage of the xor role combinator.


Well, it does seem to accomplish a similar goal. However, in your
example there is nothing about the OrganicMolecule which will prevent
me from composing it with the InOrganicMolecule, which was the primary
goal of the Fortress example. In addition in the Fortress example the
Molecule role is not coupled to the Organic and Inorganic molecules,
in your example they are.

But IMHO this is just another example of TIMTOWTDI, because your
example achieves similar goals and would likely be a valid design
approach as well.


 And from that I could see that given a large enough set of roles you
 would surely create roles which conflicted with one another on a
 conceptual level rather then on a methods/attribute (i.e. - more
 concrete) level.

I don't abide to that. If roles are conceptually modelling the same
entity their vocabulary should conflict also. Well unless some
differing coding conventions accidentally produce non-conflicting
roles. The whole point of type systems relies on the fact that
concrete conflicts indicate conceptual ones!


But part of the power of role composability is that the role itself
does not need to dictate what class it is composed into. So conceptual
conflicts cannot be determined until compostion actually occurs, and
conflicts between two conceptually conflicting roles cannot be
detected until composition time either. And of course there is nothing
to say that two conceptually conflicting roles have a concrete
conflict either (either between methods or attributes).

I think that maybe we need to seperate the concept of roles as types
and roles as partial classes, they seem to me to be in conflict with
one another. And even they are not in conflict with one another, I
worry they will bloat the complexity of roles usage.

My experiences thus far with roles in Moose have been that they can be
a really powerful means of reuse. I point you towards Yuval Kogman's
latest work on Class::Workflow, which is basically a loose set of
roles which can be composed into a highly customizable workflow
system. This is where I see the real power of roles coming into play.

- Stevan


Re: Re: class interface of roles

2006-10-02 Thread Stevan Little

On 10/2/06, Brad Bowman [EMAIL PROTECTED] wrote:

Sam Vilain wrote:
 TSa wrote:
 is this subject not of interest? I just wanted to start a
 discussion about the class composition process and how a
 role designer can require the class to provide an equal
 method and then augment it to achieve the correct behavior.
 Contrast that with the need to do the same in every class
 that gets the equal method composed into if the role doesn't
 have a superclass interface as described in the article.


 This will be the same as requiring that a class implements a method,
 except the method's name is infix:==(::T $self: T $other) or some such.

How does a Role require that the target class implement a method (or
do another Role)?


IIRC, it simply needs to provide a method stub, like so:

method bar { ... }

This will tell the class composer that this method must be created
before everything is finished.


Does the class GenSquare does GenEqual does GenPointMixin line imply
an ordering of class composition?  This would seem to be required for
the super.equal hand-wave to work but part of the Traits Paper goodness
came from avoiding an ordering.  Composition is just order insensitive
flattening.  Conflicts like the equal method in the OP have to be
explicitly resolved in the target class, either using aliases
or fully qualified names.  So there's no super needed.


The super in a Role should be late bound, so will have no relevance
when inside the role, but only make sense when composed into a class.
This is probably one of the more confusing points of roles I think.

As for how the example in the OP might work, I would suspect that
super would not be what we are looking for here, but instead a
variant of next METHOD. However, even with that an ordering of some
kind is implied.

I suppose this is again where the different concepts of classes are
roles can get very sticky. I have always look at roles, once composed
into the class, as no longer needing to exist. In fact, if it weren't
for the idea of runtime role compostion and runtime role
introspection, I would say that roles themselves could be garbage
collected at the end of the compile time cycle.


I would like a way to make one Role to require that the target class
does another abstract Role, is there already such a technique?


I am not familiar with one, but I have had this need as well lately in
using Moose roles. We have a concept in Moose (stolen from the
Fortress language) where a particular role can exclude the use of
another role, but not the ability to require it, although I see no
reason why it couldn't be done.

- Stevan


Re: Re: Re: class interface of roles

2006-10-02 Thread Stevan Little

On 10/2/06, Jonathan Lang [EMAIL PROTECTED] wrote:

This notion of exclusionary roles is an interesting one, though.  I'd
like to hear about what kinds of situations would find this notion
useful; but for the moment, I'll take your word that such situations
exist and go from there.


Well to be honest, I haven't found a real-world usage for it yet (at
least in my travels so far), but the Fortress example was this:

 trait OrganicMolecule extends Molecule
 excludes { InorganicMolecule }
 end
 trait InorganicMolecule extends Molecule end

And from that I could see that given a large enough set of roles you
would surely create roles which conflicted with one another on a
conceptual level rather then on a methods/attribute (i.e. - more
concrete) level.

- Stevan


Module/Class Authoritys

2006-08-10 Thread Stevan Little

Quick question for the group.

Can there be more than one authority?

module Foo-0.0.1-cpan:JRANDOM-http://www.foo.org-mailto:[EMAIL PROTECTED]

S11 would seem to indicate no (it states that names are made up of 3
parts), but I guess I am wondering if one of those parts can have
multiple sub-parts in it?

Thanks,

- Stevan


Re: packages vs. classes

2006-05-26 Thread Stevan Little

On 5/23/06, Sam Vilain [EMAIL PROTECTED] wrote:

Right, but we should really ship with at least a set of Meta Object
Protocol Roles, that covers the core requirements that we will need for
expressing the core types in terms of themselves;

- classes and roles
- attributes and methods
- subsets (ie constraints/subtypes)
- generics (including, by induction, nested generics)

I *think*, at this point, that's all that are necessary.


I would maybe add a protocol for instance creation. We have recently
added that to Moose, and found it very useful in terms of abstracting
out the kind of instance storage used (ARRAY based storage currently
Just Works given the right Instance sub(meta)class).

I see the instance protocol as being an important component of cross
language runtime thing. If all instances conform to, or can be made to
conform to, an base instance protocol, making Perl 6 objects which
inherit from Python objects should be fairly easy.


People can instantiate the roles that cover all that to an actual
metaclass in whatever way they like (eg,
Moose::Meta::Class-isa(Class::MOP::Class)), but not having to detect
the type and then figure out how to talk to it for at least the core of
the object system would be good.


I think the roles can serve as the core interface nessecary to
function with the base object system. As long as my metaclass .does()
the correct role, it should be able to function in the object system.
Of course the old garbage-in garbage-out rule applies, we should give
you enough meta-rope to shoot your meta-self in your meta-foot.


People can diverge completely with completely incompatible metaclasses
that don't .do those roles, the only side effect of which being that
people who write code for the standard Perl 6 metamodel will be
incompatible, and maybe some ways of setting up the class won't work
without another layer of trickery. I *think* that's what you're getting
at. Of course, it shouldn't be prohibited just because it smells.


I am not sure I like this, incompatible metaclass issues are really
really tricky and hard to debug (aka - smells *really* bad). And the
system needed to support them really can bloat the metamodel internals
in a nasty way. There are several papers out there on the subject,
none of which IMO provide a satisfactory solution. The problem then
becomes compounded by introducing the Python and Ruby metamodels into
the fray. Having a single compatability level made out of roles is not
that much of a restriction really, and keeps much of the system
interals clean and orderly. It also makes it much easier for use to
add new metamodels from other languages by just by writing a layer to
map to the core metamodel roles.

- Stevan


Re: Perl 6 design wiki?

2006-03-05 Thread Stevan Little
On 3/5/06, Mark Overmeer [EMAIL PROTECTED] wrote:
 * Stevan Little ([EMAIL PROTECTED]) [060305 02:49]:
  On 3/4/06, Mark Overmeer [EMAIL PROTECTED] wrote:
   Could we try to kind-of pre-register name-spaces for perl6 modules?

  There is no need to do such a thing, we have the 3 level naming scheme
  in Perl 6 now.
  Foo-0.0.1-cpan:JRANDOM

 I know about the naming scheme, but I am not really looking forward
 to the two new perl books Perl DBI-(Any)-cpan:TIMB
   and Perl DBI-(Any)-mailto:[EMAIL PROTECTED]

 That you have the possibility to work your way out in namespace clashes
 shouldn't directly mean that you let them happen easily.  I would really
 like to maintain a certain hierarchical name-space structure on CPAN, where
 we strive for unique names, although can work around accidental collissions.

I agree completely, and to be honest, I think the three level
namespace will be more useful in the context of a single company
and/or application, and be used more for versioning that anything
else.

 An other reason to have a kind of module/namespace pre-registration is to
 see who is (planning to go) working on what.  I think that's needed on the
 moment.

Well, to start with, there is no
C6PAN/SixPan/Whatever-it-will-be-called yet, so there is nothing to
pre-register for.

Second, Perl 6 is still (at the very least) a year away from a
(mostly) complete implementation, and that most likely will not be the
official one, and only a reference implementation that very few
people (read: audrey) will actually use in production. The official
version with Parrot and Ponie and few enough bugs to call 6.0.0 is
maybe a few years out from that. So pre-registration for namespaces in
an unfinished language is a litte premature IMO.

And lastly, I really don't like the idea anyway. It reminds me of the
domain-name squatters of the mid-90s. Just because I (with my best
intentions intact) decide that I want to write
World::Domination::Simple in 2006, does not mean that someone else in
2008+ should have to come up with another name because I registered
for the namespace I never used (and am unwilling to give up).

In addition, while I agree with you that there is some Perl 4/5 cruft
in CPAN that really should be tossed, this ignores the legacy apps
that might still need to use this code.

And as for stealing the good namespaces for writing new (and surely
better) but very different Perl 6 modules, I am not actually sure I
like that. Of course if the dream of Parrot/Ponie really works 100%,
then it will probably be a non-issue, but if it doesn't (and there is
yet to be a clear plan layed out as to how we will bridge Perl 5 -
6), then updating legacy modules to Perl 6 might be something which
really needs to happen if people are going to be able to port their
larger Perl 5 code within a reasonable amount of time and effort.

This is especailly true for modules like File::Spec or Test::More,
which so many other modules just use as if they are part of the
language. I don't mind re-working my core module to use the new
whiz-bang OO features, but I would prefer to be able to automatically
(and mechanically) convert my test suite rather than have to covert to
some type off xUnit style tests or something.

Some things may just need to stay the same, namespace intact. Anything
else would IMO further the Perl 5/6 gap that will inevitably exist
because of the depths of the language changes.

- Stevan


Re: Perl 6 design wiki?

2006-03-04 Thread Stevan Little
On 3/4/06, Mark Overmeer [EMAIL PROTECTED] wrote:
 One thing which is playing in my head already for some time is:

   Do we really want a translation from Perl5 modules into Perl6 on
   a one-to-one basis?  There are so many deceased modules occupying
   beautiful name-spaces!  Can we please re-arrange the name-spaces?

 Could we try to kind-of pre-register name-spaces for perl6 modules?

There is no need to do such a thing, we have the 3 level naming scheme
in Perl 6 now.

Foo-0.0.1-cpan:JRANDOM

- Stevan


Re: Multisubs and multimethods: what's the difference?

2006-03-02 Thread Stevan Little
On 3/2/06, Jonathan Lang [EMAIL PROTECTED] wrote:
 Can subs be declared within classes?  Can methods be declared without
 classes?  If the answers to both of these questions are no, then it
 occurs to me that you _could_ unify the two under a single name, using
 the class boundary as the distinguishing factor (e.g., a method is
 merely a sub declared within a class).  If the answer to either is
 yes, I'd be curious to know how it would work.

I would say yes.

Having subs inside classes makes creating small utility functions
easier. You could also use private methods for this, but if I dont
need to pass the object instance, why make me? I will say that I think
this distinction will be difficult at first for people steeped in Perl
5 OO.

Having methods outside of classes is less useful, and most of it's
uses are pretty esoteric, however I see no good reason not to allow it
(especially anon methods, as they are critical to being able to do
some of the cooler meta-model stuff).

A method probably cannot be invoked without first being attached to a
class somehow because it needs something to SMD off of.  But you could
almost look at a bare (and named) method as a mini-role, so that:

method unattached_method ($::CLASS $self:) { ... }

is essentially equivalent to this:

role unattached_method {
method unattached_method ($::CLASS $self:) { ... }
}

which of course brings up the possibility of this syntax:

$object does unattached_method;
^Object does unattached_method;

as a means of adding methods to a class or object (ruby-style
singleton methods).

Of course, this could also just be my not-quite-caffinated-enough
brain talking too.

Stevan


Re: Multisubs and multimethods: what's the difference?

2006-03-02 Thread Stevan Little
On 3/2/06, Jonathan Lang [EMAIL PROTECTED] wrote:
 Stevan Little wrote:
  Jonathan Lang wrote:
   Can subs be declared within classes?  Can methods be declared without
   classes?
 
  I would say yes.
 
  Having subs inside classes makes creating small utility functions
  easier. You could also use private methods for this, but if I dont
  need to pass the object instance, why make me? I will say that I think
  this distinction will be difficult at first for people steeped in Perl
  5 OO.

 Sounds reasonable.  I'm curious: can anyone think of any _public_ uses
 for subs that are declared within classes?

Same uses they would have in Perl 5 I would guess, but I don't usually
do that in Perl 5 so I am hard pressed to come up with a specific
example.

  Having methods outside of classes is less useful, and most of it's
  uses are pretty esoteric, however I see no good reason not to allow it
  (especially anon methods, as they are critical to being able to do
  some of the cooler meta-model stuff).

 OK; so declaring a method outside of a class could let you define one
 method that applies to a wide range of classes, without having to
 declare a separate method for each class.  I can see how that might
 come in handy.

  A method probably cannot be invoked without first being attached to a
  class somehow because it needs something to SMD off of.

 Why not?  IIRC, SMD differs from MMD dispatch-wise in terms of how
 many of its parameters are used (one instead of all).  If I were to
 define method foo(Complex $bar) and multi foo(Num $bar), I could
 then say foo i and expect to be dispatched to the method; whereas
 foo e would dispatch to the sub.  Likewise, i.foo would dispatch
 to the method, while e.foo would die due to improper syntax.

I suppose this is all in the details of how we do SMD. It's things
like this that make me think that SMD is just a special case of MMD,
but I think that dead horse has already been beaten here, and I am not
in the mood to reanimate it really.

 At least, that's how I see it.  What's the official position on what
 happens when you mix SMD, MMD, and/or no dispatch versions of a
 routine?

  But you could
  almost look at a bare (and named) method as a mini-role, so that:
 
  method unattached_method ($::CLASS $self:) { ... }
 
  is essentially equivalent to this:
 
  role unattached_method {
  method unattached_method ($::CLASS $self:) { ... }
  }
 
  which of course brings up the possibility of this syntax:
 
  $object does unattached_method;
  ^Object does unattached_method;

 (Wouldn't that be ^$object does unattached_method;?)

No, I am attaching the method (well role really) to the class ^Object.
There is no such thing as ^$object IIRC.

  as a means of adding methods to a class or object (ruby-style
  singleton methods).

 Hmm: I don't see a need for this with respect to adding methods to a
 class; just declare a method that takes a first parameter of the
 appropriate class.  OTOH, TIMTOWTDI: I could see arguments for
 allowing ^$object does method foo() { ... } as well.  OTGH, adding
 methods to an individual object would pretty much require the use of
 an anonymous role.  So the idea that does wraps bare methods in an
 anonymous role does seem to have merit.

exactly the conclusions I came too as well, which is one of the reason
why I really like hanging out on this mailing list

:)

- Stevan


Re: Instance attributes collision

2006-02-15 Thread Stevan Little
On 2/15/06, Rob Kinyon [EMAIL PROTECTED] wrote:
 On 2/14/06, Stevan Little [EMAIL PROTECTED] wrote:
  I think that the metaclass (stored in the pseudo-lexical $::CLASS)
  should create a number of anonymous roles on the fly:
 
 role {
  multi method a (::CLASS $self) { ... }
  multi method a (::CLASS $self, Scalar $value) { ... }
 }
 
 role {
  multi method a (::CLASS $self) { ... }
  multi method a (::CLASS $self, Array @value) { ... }
 }
 
  These roles would then be added to the metaclass using the normal
  rules of role composition. (NOTE: I assume that ::CLASS is unbound
  until the role is composed into a class, I think A12 might have stated
  this detail)
 
  Now obviously we have a conflict in our multi-methods. S12 only states
  that multi methods will be compared by their long names (name +
  signature) to resolve ambiguity, it does not state what happens when
  those long names conflict. I propose that they work just as normal
  method conflicts do, which is that both methods are excluded and the
  consuming class is then required to implement that method.

 Is it just the first multimethod a(::CLASS $self) from each role being
 excluded or are all the multimethod a(...)'s being excluded?

I would think it could be the first one only, the one where the long
name conflicts.

Stevan


Re: Instance attributes collision

2006-02-14 Thread Stevan Little
On 2/12/06, Yiyi Hu [EMAIL PROTECTED] wrote:
 For perl 6,
 Array and Scalar are in different namespace.
 So,
  class A { has $.a; has @.a };

 what will A.new.a return by default?

 An Error? or Scalar has a higher priority?

It seems to me that the best way to approach this issue is to seperate
the accessor generation from the attribute declaration.

To start with, in Perl 5, it is entirely possible to do this without ambiguity:

  package Foo;
  our $bar;
  our @bar;

This is because '$bar' and '@bar' are different names. Perl 6 should
follow this, and store the meta-objects which represent these
attributes using different names as well, so given:

  class A {
has $.a;
has @.a
  };

You would find two attribute meta-objects, one keyed to '$.a' and the
other to '@.a', and there is no ambiguity.

Now for the accessor generation portion of this question.

Accessor generation should probably take place towards the end of
class construction. You need to think of class construction as a
multi-step process, first the name is encountered:

  class A;

At this point a metaclass should be created and named A. Next the body
of the class should be evaluated within the context of the metaclass.
As each attribute declaration is encountered, it should be converted
to metaclass calls to further construct the class. So things like
this:

has $.a;

Will translate to something like this:

   $::CLASS.add_attribute(Perl6::Meta::Attribute.new(:name$.a));

Now, when the classes body has been completely evaluated, a method
should be called on the metaclass (found in the $::CLASS
pseudo-lexical variable) to tell the metaclass that that class
construction has been finished. This method should finish up the class
construction and at this point the attribute accessors should now be
generated.

Now, here is my proposal for how accessor generation should be handled.

I think that the metaclass (stored in the pseudo-lexical $::CLASS)
should create a number of anonymous roles on the fly:

   role {
multi method a (::CLASS $self) { ... }
multi method a (::CLASS $self, Scalar $value) { ... }
   }

   role {
multi method a (::CLASS $self) { ... }
multi method a (::CLASS $self, Array @value) { ... }
   }

These roles would then be added to the metaclass using the normal
rules of role composition. (NOTE: I assume that ::CLASS is unbound
until the role is composed into a class, I think A12 might have stated
this detail)

Now obviously we have a conflict in our multi-methods. S12 only states
that multi methods will be compared by their long names (name +
signature) to resolve ambiguity, it does not state what happens when
those long names conflict. I propose that they work just as normal
method conflicts do, which is that both methods are excluded and the
consuming class is then required to implement that method.

So now, if we follow the rules of role composition, when these two
anonymous roles are added to the metaclass, there will be a conflict
and class composition will fail.

So the short answer is that this:

  class A {
has $.a;
has @.a
  };

will result in a fatal compile time error, while this:

  class A {
has $.a;
has @.a
multi a ($::CLASS) {
  # do something here,.. I dont know what :)
}
  };

will not fail.

Hope this helps :)

Stevan


Re: overloading the variable declaration process

2006-02-14 Thread Stevan Little
On 2/12/06, Thomas Sandlass [EMAIL PROTECTED] wrote:
   IIRC, you can always create a new method for a class, even outside of
   its definition, simply by ensuring that the first parameter to be
   passed in will be an object of that type:
  
 method bark (Dog $_) { ... }
 
  I don't think this is true unless it is a multi method, in which case
  it is not actually a method of the of the class, but instead just
  DWIMs because of MMD and the fact we allow an invocant calling style
  freely.

 Yes, the question of ownership of methods is still
 somewhat unresolved. I think we need to distinguish
 something I've called slots in an object from free
 (multi) methods that are defined outside of the class
 definition block. BTW, do the outsiders have access
 to the private data slots with the $! twigil?

I think that multimethods defined outside of the scope of the class
should not have access to the classes data slots, it should use the
accessors. And those multimethods should live in the package in which
they are defined. The class implementation can stash refs to
multimethods which apply to it for optimization reasons, but this has
nothing to do with the language design itself.

As far as method name disambiguation, we should use the calling style
(invocant vs. normal function call) to determine which method to call.

I am sure there are other edge cases to be uncovered here as well, but
I can't think of them at the moment.

Stevan


Re: overloading the variable declaration process

2006-02-09 Thread Stevan Little
On 2/8/06, Jonathan Lang [EMAIL PROTECTED] wrote:
 Stevan Little wrote:
  Yes, that is correct, because:
 
  Dog.isa(Dog)  # true
  $spot.isa(Dog)  # true
  ^Dog.isa(Dog)  # false
 
  In fact ^Dog isa MetaClass (or Class whatever you want to call it).
 
  At least that is how I see/understand it.

 OK.  To help me get a better idea about what's going on here, what
 sorts of attributes and methods would ^Dog have?

Well, a metaclass describes the behaviors and attributes of a class,
and ^Dog is an *instance* of the metaclass. So actually ^Dog would not
actually have attributes and methods since it is an instance. That
said, I think ^Dog would probably respond to methods like these (some
of which are described in S12):

  ^Dog.name # Dog
  ^Dog.version # 0.0.1 (or something similiar of course)
  ^Dog.authority  # cpan:LWALL or email:[EMAIL PROTECTED]

  ^Dog.identifier # returns the string Dog-0.0.1-cpan:LWALL

I would like to see some methods like this:

  # dynamically add a method that
  # Dog and $spot would respond to
  ^Dog.add_method(bark = method () { ... });

Which would be like doing this in Perl 5:

  no strict 'refs';
  *{'Dog::bark'} = sub { ... };

And of course if you can add a method, you will need to be able to
fetch and delete them as well, so a get_method and remove_method
would be in order as well.

And if you can add methods, surely you can add attributes, so
(add|get|remove)_attribute would be needed.

  ^Dog.add_attribute(:label$fur, :accessrw);

Would be equivalent to saying this:

  class Dog is reopened {
  has $fur is rw;
  }

And ^Dog would also provide access to infromation about super and
subclasses as well. So superclasses and subclasses methods would
make sense too. We would also need methods to deal with Role
relationships as well.

So, given the above items, the class MetaClass might look something like this:

  class MetaClass {
  has $name is rw;
  has $version is rw;
  has $authority is rw;

  has @superclasses;
  has @subclasses;

  has %methods;
  has %attributes;

  method identifier { ... }

  method superclasses { ... }
  method subclasses { ... }

  method add_method { ... }
  method get_method { ... }
  method remove_method { ... }

  method add_attribute { ... }
  method get_attribute { ... }
  method remove_attribute { ... }
  }

So given this, you could almost look at this code:

  class Foo-0.0.1-cpan:JRANDOM {
  has $bar is rw;

  method baz (Foo $self:) { ... }
  }

As being roughly equivalent to the following code:

  ^Foo := MetaClass.new();
  ^Foo.name('Foo');
  ^Foo.version(0.0.1);
  ^Foo.authority(:cpanJRANDOM);

  ^Foo.add_attribute(:label$bar, :accessrw);
  ^Foo.add_method(baz = method (Foo $self) { ... });

Of course this is mostly unspecced, and it is still unclear exactly
how much of this meta-level API will be accessible in Perl 6 itself.
And as far the the Pugs work on this goes, we plan to have something
similar to the above available in the next release (6.28.0).

Hope this helps.

Stevan


Re: overloading the variable declaration process

2006-02-09 Thread Stevan Little
On 2/9/06, Jonathan Lang [EMAIL PROTECTED] wrote:
 Stevan Little wrote:
  Jonathan Lang wrote:
   OK.  To help me get a better idea about what's going on here, what
   sorts of attributes and methods would ^Dog have?
 
  Well, a metaclass describes the behaviors and attributes of a class,
  and ^Dog is an *instance* of the metaclass. So actually ^Dog would not
  actually have attributes and methods since it is an instance.

 Huh?  A dog can bark; so the Dog class should have a method called
 'bark'.  Or does 'can' not mean what it seems to mean?

^Dog is an instance of the MetaClass, while Dog (no ^ sigil) is the
class (actually it's a prototypical instance of the class which the
metaclass ^Dog describes, but you dont really need to know that to use
it).

  ^Dog.can(bark) # false
  Dog.can(bark) # true

This is a very important distinction. Saying Dog class has a method
called 'bark', implies the following statements are true

- Dog will respond to the method called bark.

- Given my Dog $spot, $spot will respond to the method called bark.

- ^Dog (the metaclass instance which describes a class called Dog)
does *not* respond to the method called bark.

- ^Dog (since it describes the class called Dog) manages all of the
methods which Dog and $spot will respond too, one of which is called
bark.

There is a clear line between the meta-level (where ^Dog lives) and
the user-level (where Dog and $spot) live. This is a line which is
heavily blurred in Perl 5, and in many OO languages (aside from
Smalltalk, CLOS and a few others) the meta-level is just not
accessible at all from user-land.

  That said, I think ^Dog would probably respond to methods like
  these (some of which are described in S12):

 OK; apparently, what I meant when I asked what methods and attributes
 does ^Dog have? is what you're talking about when you speak of which
 methods ^Dog will respond to.  To me, an object has whatever methods
 that it responds to.

I disagree, an object is an instance of a class. A class has the
methods that the object will respond too. You would not want to store
all the methods in each instance, it would not make sense. Each
instance needs to share a set of methods, and those methods are stored
in the class.

Well what is a class?

In Perl 5 a class is simply a package, and the subs in that package
are methods. In Perl 6 however, a class will be an instance of another
class, the MetaClass. These two things are really not that different
when you think about it.

- A Perl 5 package holds methods for you by storing them in the symbol
table. You can add, get, remove these methods from the symbol table
using the symbol table API.

- A Perl 6 class holds methods for you by storing them inside an
instance variable in an instance of the MetaClass, and you can add,
get, remove these methods by using the methods of MetaClass.

Of course you have a conceptual circulatiry issue now because well,..
what is a MetaClass? Well it could be an instance of a MetaMetaClass,
but what is that an instance of? This could go on forever (turtles all
the way down as it is sometimes called).

But in practice you either just stop and say this is as far as it
goes,  or you bootstrap your class model somehow and tie the knot.
I prefer the boostrapping as it is much more elegant and tends to
allow for much more flexibility.

^Dog.name # Dog
^Dog.version # 0.0.1 (or something similiar of course)
^Dog.authority  # cpan:LWALL or email:[EMAIL PROTECTED]
 
^Dog.identifier # returns the string Dog-0.0.1-cpan:LWALL

 Would it be valid to speak of ^$spot?  If so, what would ^$spot.name be?

There is no such thing as a ^$spot. The ^ is the class sigil, and
will hold metaclass instances only, just as variables with  % will
only holds hashes, and variables with @ will only holds arrays, etc.

  I would like to see some methods like this:
 
# dynamically add a method that
# Dog and $spot would respond to
^Dog.add_method(bark = method () { ... });
 
  Which would be like doing this in Perl 5:
 
no strict 'refs';
*{'Dog::bark'} = sub { ... };

 IIRC, you can always create a new method for a class, even outside of
 its definition, simply by ensuring that the first parameter to be
 passed in will be an object of that type:

   method bark (Dog $_) { ... }

I don't think this is true unless it is a multi method, in which case
it is not actually a method of the of the class, but instead just
DWIMs because of MMD and the fact we allow an invocant calling style
freely.

 or maybe

   method Dog.bark () { ... }

Yes that works too. But TIMTOWTDI, and each has it's own benefits.
Your above approach works fine while you are writing the code, but is
not as useful for dynamically adding a method at runtime (unless you
use eval(), but that gets ugly). Using the metaclass API dynamically
adding a method to a class at runtime is trivial, again, think of it
as being no different that doing this in Perl 5:

# deep within a function

Re: overloading the variable declaration process

2006-02-08 Thread Stevan Little
On 2/8/06, Jonathan Lang [EMAIL PROTECTED] wrote:
 Consider my Dog $spot.  From the Perl6-to-English Dictionary:
   Dog: a dog.
   $spot: the dog that is named Spot.
   ^Dog: the concept of a dog.

 Am I understanding things correctly?

 If so, here's what I'd expect: a dog can bark, or Spot can bark; but
 the concept of a dog cannot bark:
   can Dog bark; # answer: yes
   can $spot bark; # answer: yes
   can ^Dog bark; # answer: no

Yes, that is correct, because:

Dog.isa(Dog)  # true
$spot.isa(Dog)  # true
^Dog.isa(Dog)  # false

In fact ^Dog isa MetaClass (or Class whatever you want to call it).

At least that is how I see/understand it.

Stevan


Re: A proposition for streamlining Perl 6 development

2006-02-07 Thread Stevan Little
On 2/7/06, Allison Randal [EMAIL PROTECTED] wrote:
 On Feb 7, 2006, at 13:28, Yuval Kogman wrote:

  Apologies if this is insulting to anyone, but personally I think
  that Perl 6 (pugs, parrot, everything) is losing too much momentum
  lately. I think we need to seriously rethink some of the
  implementation plan.

 I understand your frustration. I even sympathize, as I had to work
 through this same frustration a few years ago. But, micromanagement
 is not the answer to lost momentum.

I really don't think that Yuval is talking about micromangement. He is
talking about refactoring. I think we can all agree that:

- Small methods are good
- Monolithic God objects are bad

Decomposing the problem into smaller and smaller problems until the
problems become manageable for a small team of volunteers to work on
and understand.

 It actually makes things worse,
 as people throw their effort into defining the problem more and more
 clearly, instead of throwing their effort into producing shippable code.

I am not sure if that is Yuval's point either, in fact I think his
point is that without defining the problem a little clearer it will be
very difficult to actually produce shippable code.

 If it makes you feel any better, pretty much all projects suffer a
 loss of momentum after the first year.

Well I dont know about Yuval, but that depresses me somewhat :(

 Parrot, on the other hand, has noticeably gained momentum the past 6
 months or so. AFAICT, this is largely due to the fact that we're
 close enough to finished that we can see the light at the end of the
 tunnel, and because Pugs reminded us to hold on to our sense of fun.

Now I am not as involved in Parrot as I am in Pugs so I might be way
off base here, but from my point of view Parrot still has a long way
to go before it runs Perl 6 code. Part of that is because the bridge
between PIR/PMCs and Perl 6 just does not exist yet (either in code,
or even conceptually). Having PGE parse Perl 6 code only gives us an
AST, it does not give us running code. And even if we have a nicely
massaged AST, running Perl 6 is not a matter of just walking the tree
and evaluating it like it is in Perl 5 (of course, I am simplifying
quite a bit here). We found (a few months ago) in Pugs that this model
just isn't robust enough, and Perl 6 is going to need a more
sophisticated runtime environment to support many of it's features.
This runtime (or as we have been calling it in Pugs the Object
Space) will need to exist on top of Parrot too since it is far to
Perl 6 specific to be implemented into the Parrot core.

This is the kind of stuff that Yuval is talking about. The missing
bits that need to exist in the nether-region between perl6-language
and perl6-internals.

We are building from the bottom-up (Parrot) and the top-down (Perl 6 -
the language) and it seems (at least to many of us on the Pugs
project) that there is a big hole somewhere in the middle.

Now, I am perfectly willing to admit that I am totally wrong and eat
every single one of my words if you can show me the missing conceptual
bridge that I am talking about. And please, no hand-waving as that
does not produce shippable code.

Respectfully,

Stevan


Re: A proposition for streamlining Perl 6 development

2006-02-07 Thread Stevan Little
On 2/7/06, chromatic [EMAIL PROTECTED] wrote:
 On Tuesday 07 February 2006 14:17, Yuval Kogman wrote:
  De-facto we have people running PIL on javascript.
  It works more than parrot does.

 No, it works *differently* from Parrot, just as an LR parser works differently
 from an LR parser.

 Don't make the mistake of thinking Wow, it took Parrot X months to get a
 working PGE, while the Pugs version only took Y weeks, especially because
 the Pugs version had the benefit of looking at *already designed, debugged,
 and tested* Parrot code.

The Pugs project and the Parrot project have had very different goals
actually (at least Pugs did from the early days). Pugs aimed to be
able to evaluate Perl 6 code, as a way of testing the language
features and design. It did not really attempt (until the PIL work
began) to provide a VM for Perl 6 to run on. And even the PIL work
began as a way to strip Perl 6 down to a more managable core calculus
which was easier to interpret, the multiple backends seemed to grow
out of that as a side-effect.

So I guess what i am saying is that I agree with you, comparing Pugs
development to Parrot development does not make sense. However, I
think we arrive at that conclusion from different angles.

It seems to me that Pugs has taken a top-down (more language centric)
approach, and Parrot has taken a more bottom-up (runtime/VM centric
approach), and in my eyes, there is a big gapping hole in the middle
(see my response to Allison's post for details about the big gapping
hole).

Much of what Yuval is proposing is ways to fill that hole and to
decompose and refactor the current Perl 6 development process so that
we can have a real production Perl 6 to play with that much sooner.
But also have a Perl 6 that some PhD canidate can re-write the
type-checker for his thesis project or that some volunteer hobbiest
can re-implement the core in FORTH or some open source hacker can hack
the circular prelude to make the Schwartzian transformation that much
quicker and efficient.

IMHO breaking down the project into smaller more digestable chunks
carries as much risk of failure as putting all the eggs into single
Parrot nest.

At the very least, this is a debate worth having, especially since we
have all been waiting very patiently for so many years now.

Once again...

Respectfully,

Stevan


Re: overloading the variable declaration process

2006-02-07 Thread Stevan Little
On 2/7/06, Matt Fowles [EMAIL PROTECTED] wrote:
 Stevan~

 I am going to assume that you intended to reply to perl 6 language,
 and thus will include your post in its entirety in my response.

Yes, sorry... I missed the reply to all button on the gmail UI by a
few pixels I guess. Thank you for forwarding.

 Now that everyone is on the same page, I will go about responding


# snip some code 

 
  class Pipe::Stem {
 has $composed_of;
 has $color;
 has $length;
 has $filter = bool::false;
  }

 so far I am mostly with you, except one question.  Does has $filter =
 bool::false; just provide a default?

Yes, that is a default value. I assume that most Pipe smokers don't
like filters in their pipes, I might be wrong on that one because I am
not a pipe smoker :)

  You would then model the different pipes you sell;
 
  class MagrittePipe {
  has $stem = Pipe::Stem.new(
   :composed_ofebony,
   :colorblack,
   :lengthshort
   );
  has $bowl = Pipe::Bowl.new(
   :composed_ofmahogany,
   :colorbrown,
   :sizemedium
   );
  }
 
  Now, you might say, why not make the MagrittePipe an instance of Pipe,
  and give the Pipe class a few more attributes, like a name. Well, if
  you did that then you couldn't subclass it of course.

 Actually, I was going to ask why not make MagrittePipe inherit from Pipe.

Ooops, forgot that part it should infact inherit from Pipe. And of
course you can do that dynamically with the metamodel ;)

  Well, using introspection, it becomes very simple to discover various
  qualities about your inventory, enough to probably even autogenerate
  the HTML pages for your online-web store (powered by Perl 6 of
  course). And lets not forget the uber-cool Perl 6 Object Database
  which you are using to store your real-time inventory in (all
  metamodel powered of course). And of course if you want, you can use
  the DistributedObjectProxy metaclass which will automatically make
  your objects distributed so that your door-to-door Pipe saleforce can
  update your inventory in real time from their cellphones. And your RD
  department can use the built-in (but as yet unspeced) logic
  programming features of Perl 6 to mine your customer information from
  your (previously mentioend) object database and genetically grow
  new, more desireable Pipe products (which is easy to do since your
  metaclasses are programatically composable (and no I don't mean eval
  $code)).

 I think you mis-understand me.  I do not question the value of a
 powerful meta-model.  Quite the contrary I want to see Perl 6 have a
 meta-model more powerful and accessible then CLOS.  I see it as a
 necessity for a language that plans to truely scale in the future.

 What I do question is the usefullness of having bare class names
 represent these prototype objects.  I just don't really understand
 what they are for or do.

Well, to be totally honest, I think only Larry truely understands
their usage, but to the best of my understanding they are intented to
serve a number of roles;

(Larry, please correct me if I am wrong here)

- to allow for introspection of the class.

After all ^Foo.can() is really just a series of method calls to the
Foo metaobject. And besides ^Foo.meta.can() is 5 more characters to
type!!

- provide an invocant for class methods.

Larry does not like the class-method/instance-method distinction (in
fact it seems he doesn't even like the class/instance distinction
either), and has declared that a class method is really just a
method of the class which does not access any instance attributes.
Well, this complicates the type signature of the invocant, and we need
an invocant that the type-checker can check.

In Perl 5, classes were just package names which were just strings.
This will not work in Perl 6 in the presence of a reasonably decent
type checker, the class needs to be *something*. Now Larry has also
declared  that he does not like the idea of a class object, I think
this is because that means that a properly typed method signature for
a class method would look like this:

class Foo {
method foo (Class $class:) {
say I am a class method, and proud of it;
}
}

According to the signature, this method takes any Class instance as an
invocant. Well
thats just not right because it should only accept the Class instance
which represents the Foo class. But we can't (at least I dont think we
can) be that specific, at least not easily enough to also allow this
method to be called by an instance of Foo as well.

So, the solution,  use prototype instances for class objects. So
now we can properly type our class method for both Foo and $foo like
this:

class Foo {
method foo (Foo $class:) {
say I am a class method, and proud of it;
}
}

And whalla, 

Re: A proposition for streamlining Perl 6 development

2006-02-07 Thread Stevan Little
On 2/7/06, chromatic [EMAIL PROTECTED] wrote:
 On Tuesday 07 February 2006 15:56, Stevan Little wrote:

  The Pugs project and the Parrot project have had very different goals
  actually (at least Pugs did from the early days). Pugs aimed to be
  able to evaluate Perl 6 code, as a way of testing the language
  features and design. It did not really attempt (until the PIL work
  began) to provide a VM for Perl 6 to run on.

 In my mind, that's the most valuable thing Pugs could do.

Well, a few months ago I would have disagreed, but now I agree with
you, by taking this down the VM level (which is that the PIL^N/PIL2
runcore is focusing on) is good research for eventually connecting
this all to Parrot.

I am glad we agree here.


  And even the PIL work began as a way to strip Perl 6 down to a more
  managable core calculus which was easier to interpret, the multiple backends
  seemed to grow out of that as a side-effect.

 But they're not free to support.

Well yes that is very true, but that was a learning process. It helped
uncover some of the deficencies in the first PIL implementation (most
notable the lack of OO support). It also lead to the development of
the Object Space sub-project which is aiming to clarify how we get
from Perl 6 to something that is executable in an environment which
supports all the features designed.

These are both things which the Parrot project and the Perl 6 design
project did not address from what I can see. Only after going down
some highly experimental paths did this reveal itself.

So while I agree, they are not free to support, I would argue that
they are RD prototypes and so (to some degree) disposable, and the
benefits they have brought in terms of insight into Perl 6 the
runtime (not the language, and not the VM, but somewhere in between)
are very vaulable.

 Now I'm not arguing that the existence of multiple backends takes effort away
 from a single unified backend.  This is open development.  People work on
 what they want to work on.

Exactly Yuval's point. People want something interesting enough to
pique their interest, but small enough to digest for weekend/nighttime
hacking sessions. If Perl 6 was broken down in such a way as he
proposes, maybe it would attrack more people? or maybe it won't.
Neither I or you knowt that, we can only guess.

 Still, finding the greatest common factor of features between LLVM, Scheme,
 Spidermonkey, classic Pugs, Parrot, the CLR, the JVM, Perl 5, and whatever
 other VM is out there means pushing a lot of things up the implementation
 stack.

Sure that's one way to look at it, but it does not need to be that
way. Reducing Perl 6 down to a core calculus like PIL actually makes
it easier to target any backend you want. And the new PIL^N/PIL2
runcore will make it even easier since all that will be required will
be that you create a PIL^N runtime, all the
metamodel/container/boxed-type prelude will either be written in PIL^N
or in Perl 6. Then the Perl 6 - PIL2 part can be written using
PGE/TGE/Parsec/whatever.

IMHO this design direction (which makes multiple backends almost
trivial) makes for a better more modular and decoupled design in
general, which is surely a good thing for all projects involved
including Parrot.


  Much of what Yuval is proposing is ways to fill that hole and to
  decompose and refactor the current Perl 6 development process so that
  we can have a real production Perl 6 to play with that much sooner.

 I agree that that's his goal.  I disagree on its appropriateness.

What is inappropriate about it? He is questioning the current
direction of an open source project which has be regarded as many to
be mearly vaporware. Sure you and I know that Perl 6 is chugging right
 along and making great strides, but until Pugs many people considered
Perl 6 to be a joke at best, and total vaporware at worst.

I think Yuval has every right to question the direction, and to make
suggestions as to how he thinks it can be improved upon. He has put in
time on the project, maybe not as much as others, but enough that I
think he has a right to speak up if he wants. What is so wrong with
that?

 There are people who can write a bootstrapping compiler from the top down in
 such a way that normal people can write the user-level primitives in that
 language.  I've met those people.  I'm not one of them.  There are precious
 few of them for any language, much less Perl 6.

Hmm, quite true, but I think that is mostly because the texts on the
subject are so dense and there is a severe lack of hackable projects
out there that people can contribute too that don't involve some
esoteric language meant to explore some equally esoteric concept.

However, that said, the idea of bootstrapping compilers is
progressively getting more mainstream. Many of the recent languages 
which have sprung up for the CLR are moving towards bootstrappability.
The new version of Scala is written in Scala. So maybe, as more and
more people do it, they will find

Re: A proposition for streamlining Perl 6 development

2006-02-07 Thread Stevan Little
On 2/7/06, Allison Randal [EMAIL PROTECTED] wrote:
 On Feb 7, 2006, at 15:31, Stevan Little wrote:
 
  Now I am not as involved in Parrot as I am in Pugs so I might be way
  off base here, but from my point of view Parrot still has a long way
  to go before it runs Perl 6 code. Part of that is because the bridge
  between PIR/PMCs and Perl 6 just does not exist yet (either in code,
  or even conceptually). Having PGE parse Perl 6 code only gives us an
  AST, it does not give us running code. And even if we have a nicely
  massaged AST, running Perl 6 is not a matter of just walking the tree
  and evaluating it like it is in Perl 5 (of course, I am simplifying
  quite a bit here). We found (a few months ago) in Pugs that this model
  just isn't robust enough, and Perl 6 is going to need a more
  sophisticated runtime environment to support many of it's features.
  This runtime (or as we have been calling it in Pugs the Object
  Space) will need to exist on top of Parrot too since it is far to
  Perl 6 specific to be implemented into the Parrot core.
 
  This is the kind of stuff that Yuval is talking about. The missing
  bits that need to exist in the nether-region between perl6-language
  and perl6-internals.
 
  We are building from the bottom-up (Parrot) and the top-down (Perl 6 -
  the language) and it seems (at least to many of us on the Pugs
  project) that there is a big hole somewhere in the middle.

 You imply here that obstacles to implementing Pugs are necessarily
 obstacles to implementing Perl 6. That's not entirely accurate.

Well, the first obstacle I see to implementing Perl 6 can be fixed
with the object space work, and I do not see the Perl 6 Object space
work as being Pugs specific at all. From work I and others have done
on the meta-model  as well as the container types, it seems clear that
we need a very robust Perl 6 runtime environment. And currently Parrot
does not provide enough of that environment. This is not to say that
Parrot *cannot*, only that it does not currently. And in my opinion,
Parrot shouldn't cater this much to Perl 6 anyway. Parrot's object
model is sufficently generic to support the object model of most of
the current crop of dynamic languages, but that will not be enough for
Perl 6. You just can't compile all the runtime dynamism into PIR and
PMCs, you will need a runtime environment (an object space) to support
it.

The next obstacle to implementing Perl 6 I see is the
type-checker/inferencer, this is not the job of Parrot, or of PGE. It
a the job for a type inferencer, of which I don't see work on one
currently outside of Pugs and Yuval's Blondie work.

Then there is the prelude. Why write Perl 6's built-ins in PIR when
you can write it in Perl 6? Assuming the Perl 6 codegen is good enough
of course. And modern compiler and optimization technology has been
doing those things since the late-80s (there are many studies of how
compiled Ada code was faster and better than expert hand coded
asssembler, there are just some things a computer can do better than a
person).

I think Pugs and Parrot/PGE share many more obstacles than you might think.

 But, there is another route, and we're working on it at the same
 time. From the Parrot perspective, PGE parses the source, its output
 is translated to an AST (or a couple of intermediate ASTs), and that
 is translated either to PIR, or directly to bytecode.

But this is my point, this won't be enough to support all that Perl 6
is to be. PIR  PMCs simply are not enough to have full metaclass
support, roles (at compile/class composition time, and runtime),
traits, etc. And lets not forget that (to quote Larry in S02 i think)
Perl 6 is an OO engine. Which means that container types like
Scalars, Arrays and Hashes are objects now too. These things map
nicely to some of the current PMCs, but they are not boxed inside the
object metamodel, and until they are they are not extendable and
usable in the way the language design prescribes.

The Pugs project started out with an AST which was then evaluated,
which is similar to your AST translated to PIR, and we just found it
wasn't enough. Perl 6 is just simply to dynamic a language for that.

 I'm working on a prototype of this now in Punie, specifically so we can try 
 out the
 whole path from source code to bytecode.

I am familiar with your Punie work as I read your use.perl journal and
the Perl 6 meeting notes regularly. But IIRC Punie is a compiler for
Perl 1 is it not? Perl 1 is a very very very long way from Perl 6.

 Perl 6 will get implemented.

Oh, of that I have no doubt. Never did, and neither does Yuval (if I
may speak for him while he is asleep :). But all that we are trying to
do here is shake out some cobwebs, a little spring cleaning if you
will.

Stevan


Interesting Paper on Prototype Based OO w/ Multi-Methods

2006-01-27 Thread Stevan Little
Hello All,

Recently on #perl6 putter found the Slate language
(http://slate.tunes.org/) in our search for some information about
Smalltalk. Slate is a prototype based OO language which uses multi
method dispatch instead of more traditional method dispatch. As I
flipped through some of the papers on the site, I couldn't help
thinking back to some of the more recent musing of Larry on the Perl 6
object model. The paper which is most complete is this one:

http://tunes.org/~eihrul/ecoop.pdf

Or for those with shorter attention spans, there are some slides which
give a high level overview of what is in the paper. That can be found
here:

http://tunes.org/~eihrul/talk.pdf

I think there is definitely some valuable information to be found in
here, which we can use in the further development of the Perl 6 obejct
model.

Stevan


Re: as if [Was: Selective reuse of storage in bless.]

2006-01-26 Thread Stevan Little
On 1/25/06, Jonathan Lang [EMAIL PROTECTED] wrote:
 Larry Wall wrote:
  But my hunch is that it's
  a deep tagmemic/metaphorical problem we're trying to solve here.
  Such issues arise whenever you start making statements of the form
  I want to use an A as if it were a B.  The problem is much bigger
  than just how do I translate Perl 5 to Perl 6.  It's questions like:
 
  What makes a particular metaphor work?
  Will the cultural context support use of an A as if it were a B?
  How do we translate the user's thoughts to the computer's thoughts?
  How do we translate one user's thoughts to another user's thoughts?
  How do we know when such a translation is good enough?
  How do we know when our mental model of an object is adequate?
  How do we know when the computer's mental model of an object is 
  adequate?
  What does adequate mean in context?
  Will the culture support partially instantiated objects?  :-)
 
  That's tagmemics, folks.  The main problem with tagmemics is that, while
  it helps you ask good questions, it doesn't give you easy answers for 'em...

 Let me take a (feeble) crack at this:

 It sounds like we're talking about something vaguely akin to C++'s
 typecasting, where you treat an object of a given class as if it were
 an object of a different class.

Actually this might not be a bad approach in this case. Take this for instance:

method foo (Foo $self, $key) {
((Hash) $self){$key}
}

The syntax is ugly, but it makes what you are doing more explicit. I
would also think that in most cases this could be compile time checked
(if we can check $self's type (Foo), we can make sure Foo does/isa
Hash).

Here are some other ideas for a typecasting syntax using as for the
keyword (which IIRC is taken for coercion??):

$self as Hash {
 # $self is treated as a Hash inside the block
 $self{$key} = $value;
}

# it could also return a wrapped
# $self for use in wider scopes
my $h = $self as Hash;
$h{$key} = $value;

Anyway, it's just a early morning (not enough coffee in my system) thought.

Stevan


Re: as if [Was: Selective reuse of storage in bless.]

2006-01-26 Thread Stevan Little
On 1/26/06, Rob Kinyon [EMAIL PROTECTED] wrote:
 On 1/26/06, Stevan Little [EMAIL PROTECTED] wrote:
  Actually this might not be a bad approach in this case. Take this for 
  instance:
 
  method foo (Foo $self, $key) {
  ((Hash) $self){$key}
  }
 
  The syntax is ugly, but it makes what you are doing more explicit. I
  would also think that in most cases this could be compile time checked
  (if we can check $self's type (Foo), we can make sure Foo does/isa
  Hash).
 
  Here are some other ideas for a typecasting syntax using as for the
  keyword (which IIRC is taken for coercion??):
 
  $self as Hash {
   # $self is treated as a Hash inside the block
   $self{$key} = $value;
  }
 
  # it could also return a wrapped
  # $self for use in wider scopes
  my $h = $self as Hash;
  $h{$key} = $value;

 Isn't typecasting a DesignSmell? This kind of overloading is, imnsho,
 going to cause more coding bugs and is going to be considered a design
 flaw in P6.

General typecasting is probably a really really bad idea, I agree. But
some tightly controlled typecasting (shhh dont call it that or the
C/C++/Java programmers will freak out), might be useful in this case.
If you like, you can think of this as coercion, and not typecasting,
in fact this is probably the better word for it anyway.

 If there is need to treat something as a Hash, then provide it with a
 postcircumfix{} and leave it at that. It's highly unlikely that you
 will want to add Hash-like behavior to something that already has a
 postcircumfix{} because it probably has that behavior already.

Well this is in relation to how to deal with an object which is a
blessed p6hash, in which case you may or may not want to have a
^Hash-like interface for it (you might even want to overload the
^Hash-like interface too).

So, let me explain myself (hopefully) more clearly.

Lets say we treat infix:as as a general purpose coercion operator.
So that things like:

$num as Str;

will pretty much DWIM since a number can be easily coerced into a
string (at least 99% of the time, I am sure some of the math whizzes
will tell me different so I leave the 1% for that ;).

Now, in order for C$self as Hash to make sense, $self would have to
be coercable into a Hash in some way. If $self is a blessed p6array
this might not make that much sense, so we would die because the
coercion failed. However, if $self is a blessed p6hash, then it would
make plenty of sense (IMO at least). It would allow us to get at the
underlying representation without having to sacrifice flexibility in
the class from which $self came. Basically you could do things like
this:

class Golum;

method new (Golum $class, Hash %params) {
$class.bless(%params);
}

method postcircumfix:{} (Golum $self, Any $key, Any $value) {
 die Nasssty Hobbitses if $value.does(Hobbit);
 $self as Hash {
$self{$key} = $value;
}
}

We could also do this with the p5hash representation too, assuming we
have a ^P5Hash of some kind (which is probably not a bad idea really).

Anyway, I now have some more caffine in my system (coffee,.. yummy),
not that it makes the idea any better, but at least it is more
detailed ;)

Stevan


Re: as if [Was: Selective reuse of storage in bless.]

2006-01-26 Thread Stevan Little
On 1/26/06, Rob Kinyon [EMAIL PROTECTED] wrote:
 On 1/26/06, Stevan Little [EMAIL PROTECTED] wrote:
   If there is need to treat something as a Hash, then provide it with a
   postcircumfix{} and leave it at that. It's highly unlikely that you
   will want to add Hash-like behavior to something that already has a
   postcircumfix{} because it probably has that behavior already.
 
  Well this is in relation to how to deal with an object which is a
  blessed p6hash, in which case you may or may not want to have a
  ^Hash-like interface for it (you might even want to overload the
  ^Hash-like interface too).

 [snip]

  Now, in order for C$self as Hash to make sense, $self would have to
  be coercable into a Hash in some way. If $self is a blessed p6array
  this might not make that much sense, so we would die because the
  coercion failed. However, if $self is a blessed p6hash, then it would
  make plenty of sense (IMO at least). It would allow us to get at the
  underlying representation without having to sacrifice flexibility in
  the class from which $self came. Basically you could do things like
  this:
 
  class Golum;
 
  method new (Golum $class, Hash %params) {
  $class.bless(%params);
  }
 
  method postcircumfix:{} (Golum $self, Any $key, Any $value) {
   die Nasssty Hobbitses if $value.does(Hobbit);
   $self as Hash {
  $self{$key} = $value;
  }
  }

 How about just inheriting from Hash?

 class Gollum extends Hash;

 method postcircumfix:{} (Golum $self, Any $key, Any $value) {
  die Nasssty Hobbitses if $value.does(Hobbit);
 $self.NEXT.{}( $key, $value );
 }


Well, postcircumfix:{} is not just for emulating Hash :)

class struct;

has @.struct_def;
has $.struct_name;

method postcircumfix:{} ($class, Array of Pair @struct, $name) {
$class.new(
struct_def = @struct,
struct_name = $name
);
}

Then you could do something like this maybe:

my $jedi_struct = struct{(
   first_name = 'Luke',
   last_name  = 'Skywalker'
)} = jedi;

At least I assume you can, taking advantage of the a class is
prototypical instance thing to call postcircumfix:{} like that.

But I just might have had too much caffine at this point though ;P

Stevan


Perl 6 OO and bless

2006-01-20 Thread Stevan Little
 On Thursday 19 January 2006 21:53, Stevan Little wrote:
  With p5, you /can/ get to the underlying data structure. This is a
  break which will hamper the backwards compatibility effort I think.

 With Perl 5, you can *appear* to get to the underlying data structure.  Yet
 tie() is basically free on Ponie and there's a metaclass mediating access to
 the underlying storage.  I think that makes the problem solvable.

Excellent.

 (Does using an alternate type of storage mean you need an alternate metaclass?
 Perhaps, perhaps not -- but the practical effects of syntax have to come from
 somewhere.)

Actually I was thinking this might be the best approach. I have been
dabbling more and more with CLOS lately and am not seeing where a
full-fledge attribute meta-object is probably a really good idea (in
the current model the meta-attribute is very very slim).

 As long as you can use Perl 5 classes in Perl 6 without rewriting all of the
 Perl 5 code, I'm happy.

Yes, this is the ultimate goal. I never wanted to get rid of bless,
only to resolve what I saw as an inconsistency with the use of bless
and some of the other aspects of the Perl 6 design.

Stevan


Re: as if [Was: Selective reuse of storage in bless.]

2006-01-20 Thread Stevan Little
Larry Wall wrote:
 On Fri, Jan 20, 2006 at 09:35:13PM +0800, Audrey Tang wrote:
 My original intent was #2, hence the wording in A12.  But to speak to
 some of Stevan's concernes, there's something going on here which is
 not quite Object does Hash.  It's more like Object can do Hash,
 in the linguistic sense that a Noun can do Verb, but nonetheless
 remains a noun.  A fallback role is not the same as a normal role.
 Maybe there's some way to mixin in a fallback Hash role without
 clobbering a real Hash role that is already there, so that if your
 Hash container is an object you don't see methods for its keys.

 Something like this might also let us distinguish p5ish scalars that
 are simultaneously Num and Str from scalars that, say, intrinsically
 do Num but can emulate Str in a pinch without caching the result.
 I don't think we have a good way of expressing that distinction right
 now.

I agree it is a hairy subject, but the more I think about this (and
the more i read about and play with CLOS) I think we might be able to
accomplish something very close to this by creating more special
purpose attribute meta-objects.

By moving much of the actual attribute accessing work to the attribute
meta-object, we can very easily have arbitrary object types since
all their access is mediated through the attribute meta-object.

In CLOS this would be accomplished by subclassing the standard-class,
and telling it to use the different attribute meta-object by default.
The of course you slap a juicy LISP macro around it, and you are ready
to go. Mm LISP macros :)

Basically my point is that the meta-classes and meta-objects govern
the behavior of the classes and object. So if we want to change the
behavior of our classes and objects, we just subclass the meta-classes
and meta-objects and specialize the behavior as we desire.

 This seems to imply that a given role like Hash could have two default
 implementations--one for an actual Hash container, and one that emulates
 a Hash by deferring to the Object.  It's sort of like a role that can
 delegate back to its own object.

This should all be possible with attribute meta-objects. Basically
when we encounter this type of need (in p5-p6 translated classes, or
otherwise), the compiler (or possibly the translator) needs to
discover this need, and change the metaclass appropriately. The self
delegation then Just Works.

Of course this is all just hand-waving right now since the current
metamodel does not support such deep magic. But hey, I have been
thinking it might be time for a v3 soon anyway :)

 Such issues arise whenever you start making statements of the form
 I want to use an A as if it were a B.  The problem is much bigger
 than just how do I translate Perl 5 to Perl 6.  It's questions like:

 What makes a particular metaphor work?
 Will the cultural context support use of an A as if it were a B?
 How do we translate the user's thoughts to the computer's thoughts?
 How do we translate one user's thoughts to another user's thoughts?
 How do we know when such a translation is good enough?
 How do we know when our mental model of an object is adequate?
 How do we know when the computer's mental model of an object is adequate?
 What does adequate mean in context?

I am actually working with Rob Kinyon on a meta object protocol for
Perl 5 for our $work. It does not try to make Perl 5 anything it is
not, instead it only attempts to define the workings of the Perl 5
object system and provide clean hooks into it. It is in the very early
stages, and needs lots of testing, but it might help to bridge the two
models.

 Will the culture support partially instantiated objects?  :-)

Hmm, do you mean lazy objects? As in, only instantiated as much as is
absolutly necessary at a particular moment?

I recently read a paper on an extended version of CLOS (yay CLOS)
which demonstrated how lazy classes could be built, including ones
with strict initialization orders ($a must be initialized before $b,
but $b depends on $c, etc). But maybe this is not what you mean.

Or is this the class but undef idea again?

Audrey and I have solved this by creating a 'p6undef' repr type
which allows the class to be instantiated and methods called on it,
but if you try to access anything other than basic meta information,
it will fail (because it's just undef).

Actually, I think this partial object thing needs it own thread
really. But I will let you decide when you are ready for that one :)

Stevan


Re: Perl 6 OO and bless

2006-01-19 Thread Stevan Little

On 1/18/06, chromatic [EMAIL PROTECTED] wrote:
 On Wednesday 18 January 2006 18:54, Stevan Little wrote:
 Or are you thinking that a Perl 6 value should be blessed into a  
Perl

 5 package?

That's closer to what I had in mind.

 I think there is a real serious issue here since the hash the Perl 5
 package would be expecting is a ref to an HV, and the Perl 6  
value it

 would be getting would be an instance of the ^Hash class (itself a
 subclass of ^Object). This is actually where i see the fundemental
 problem with a Perl 6 bless which is capable of blessing Perl 6
 references. There are no Perl 6 references like we had in Perl 5,
 they are *all* objects now. Would not the Perl 5 layer see the  
Perl 6

 instance of ^Hash as an object? If not, then we must already have a
 Perl 6 opaque (the ^Hash instance) to Perl 5 HV converter/proxy/ 
magic-

 jellybean/thunk so I don't need to write it :)

Why would Perl 6 bless() bless references?  I've always seen it as  
specifying
the underlying storage container for the object's instance data.   
(Hey, my
last rigorous reading of S12 predates my current project.  I could  
be wrong.)


If that predates the latest update then you should read again. It  
hasn't changed all that much on this subject though so maybe not.


I think the problem is that S12 is kind of fuzzy about this  
underlying storage/alternate repr for opaque issue. Without a  
really clean and well reasoned description of all that, and how it  
all works together there will be little hope of Perl 6-Perl5  
interoperability on the level you desire.


If Ponie is there and this code runs on Parrot and Ponie uses Perl  
5 PMCs,
they're theoretically available to Perl 6, with the proper  
invocations or

magic or thunking or whatever.


Well, yes, we can push this all down to Parrot, which IMO is the  
right place for it to be handled. But in that sense then Perl 6's  
interaction with Perl 5 will be no different than Perl 6's  
interaction with (Python | Ruby | Tcl | etc). Which means there will  
be some restrictions on the depth of the interaction.


If we want to have the level of interoperability which you seem to  
think we should have (and I tend to agree with you that it would be  
nice), then we need to either;


1) Have a Perl 6 OO - Perl 5 OO thunking layer

This would mediate things between the two OO models so that neither  
would have to be restricted by the other. This would be possible with  
some minor (but fairly complex) extensions to the Perl 6 MOP.  
Basically we would need to create a Perl 5 MOP of sorts which would  
have the appropriate thunks in the appropriate placed to make things  
Just Work.


2) Force some basic rules/restrictions upon the interoperability.

Well to start with, if Perl 5 code would need to treat the Perl 6  
code as black boxes. It wouldn't be able to do $self-{attr}, it  
would have to do $self-attr(). The Perl 6 code would have to handle  
the Perl 5 data structures in a similar way (not sure the details of  
that though). There would also need to be some rules about  
inheritence. Perl 6 uses the C3 algorithm to determine the method  
resolution order, while Perl 5 uses the depth-first-left-to-right  
approach. This would mean that a Perl 5 class which uses multiple  
inheritence with some Perl 5 classes and some Perl 6 classes would  
have a rather hairy time determining the method resolution order.  
Maybe we would say that the Perl 6 class would *have* to use pre- 
order (depth-first-l-to-r) and could not use C3.


I could go on here, but there are enough mismatches between the two  
OO models that there would have to be some kind of ruleset.



 Or maybe you are you thinking that a Perl 6 class can inherit from a
 Perl 5 class?

Absolutely.


See the inheritence/MRO mismatch I described above. This would apply  
here big time. It is not a trivial issue either.




 To be honest, i think this is better handled with delegation, and  
can

 even be automated using the attribute delegation features described
 in A/S12.

I have serious doubts about round-tripping with delegation, having  
tried to do
it.  I want to subclass a Perl 5 class with Perl 6 code and use  
objects of
that class within Perl 5 code without them having to know that I'm  
doing

something sneaky.

It'll be a true pity if that's *truly* impossible.


Maybe delegation would be nasty, but so would be mixed MROs. You say  
TOE-mato, I say TOW-mAto.



 The biggest problem with this would be object initialization. The
 normal Perl 6 BUILDALL/BUILD code could not be used here since  
Perl 5
 does not have the meta-object protocol to support such behaviors,  
nor

 is there a common enough Perl 5 object initialization idiom to work
 with here. The end result is that you probably end up having to do a
 bunch of manual initialization code.

Sure, but that's a per-representation thunking layer writable in  
Perl 6 code.
It might be somewhat tricky, but it's not completely hideously

Perl 6's bless is (seriously) broken

2006-01-19 Thread Stevan Little

Hello,

I am forking this off the Perl 6 OO and bless thread since that  
seems to have gotten bogged down in what it all means to Perl 5  
interoperability. This was not really my intent with the original  
thread, but I think it is still a fruitful discussion so I will re- 
make my original point here with more detail.


First I need to establish a few things on which my argument rests.

So, S02 says that Perl 6 is an OO engine. Which means that a hash is  
not a literal thing but an instance of the class ^Hash. This means  
that a hash now has methods which can be called on it, and inherits  
from ^Object.


Because @Larry does not want the OO-ness of the language to get in  
the way of doing ones job, all the methods of ^Hash are either  
transformed into pseudo-built-in-functions using macros (see the Hash/ 
delete/UnaryForm part of S29), or would be aliased as multi-subs  
which dispatch using MMD.


Take this (very simplified) pseduo-code for exists:

  method Hash::exists (^Hash %h: Any $label) return Bool {
  %h{$label} ?? bool::true !! bool::false
  }

And lets assume that a macro has been written to make it callable in  
the built-in function style which will transform this:


  exists %h{'foo'}

Into this:

  %h.exists('foo');

Now, what happens when we bless a hash.

  class Foo {
  method new ($class: %params) {
  $class.bless(%params);
  }
  method bar ($self:) { ... }
  }

The result of Foo.new is an instance of ^Foo. In Perl 5, the hash  
would be tagged with the package name it was blessed into, but it  
would still be a hash reference, only now you could also call methods  
on it. This *won't* work the same in Perl 6 though. This is because,  
what is blessed is not a literal hash, but an instance of ^Hash. If  
we follow the Perl 5 logic, then we can now call methods on this  
blessed hash, but we cannot use the hash built-in functions since  
they are just macro transformations into method calls. Take this code  
example:


  my $foo = Foo.new({ one = 1, two = 2 });
  exists $foo{'one'}; # this will not work

The reason this the above code will not work is because exists $foo 
{'one'} will be transformed by the macro to $foo.exists('one'),  
which will fail since no Foo::exists exists. Even if we tried to do  
this (and assuming the macro would DWIM):


  Hash::exists $foo{'one'};

This would fail anyway since Hash::exists is expecting a ^Hash  
instance as it's invocant arg, and not a ^Foo instance, so it would  
fail on the parameter/argument type check.


I think this is a deep problem with how bless works, how the  
container types work, and maybe even how our MMD system works. I  
think we need to have a well reasoned solution to this which is  
devoid of any magic hand waving.


Thanks,

Stevan





Re: Perl 6's bless is (seriously) broken

2006-01-19 Thread Stevan Little


On Jan 19, 2006, at 4:10 PM, Rob Kinyon wrote:

Packages don't have anything to do with the class
system.


Actually ^Class.isa(^Package) ;)

Stevan



Re: Perl 6's bless is (seriously) broken

2006-01-19 Thread Stevan Little

Juerd,

On Jan 19, 2006, at 4:10 PM, Juerd wrote:

Stevan Little skribis 2006-01-19 15:45 (-0500):

  class Foo {
  method new ($class: %params) {
  $class.bless(%params);


Wouldn't that be %params.bless($class), or more directly,
%params.blessed = $class?


Nope, according to S12:

  As in Perl 5, a constructor is any routine that calls bless. Unlike
  in Perl 5, you call it as a method on the class, passing the  
candidate

  as the first argument.

It then does on to give this code example:

  $object = $class.bless({k1 = $v1, k2 = $v2, ...});

In fact all example using bless us it as a method of the $class.


This *won't* work the same in Perl 6 though. This is because,
what is blessed is not a literal hash, but an instance of ^Hash.


The mistake here is that Foo doesn't does Hash, I think.


But we cannot automagically inject a role into a class, for a number  
of reasons.


1) thats just plain evil
2) what if the role conflicts with other roles being does-ed by Foo?  
Debugging hell there.
3) What if Foo wants to have a .keys, .value, .exists, etc? Do they  
shadow the Hash version? What if Foo.keys is implemented using  
Hash.keys? Many issues abound here.



Sure, in Perl 5, you could have different kinds of references as
instances of the same class. But I don't recall ever having  
encountered

that.


bless([] = 'Foo');
bless({} = 'Foo');
bless(\*Foo = 'Foo');
bless(\(my $var) = 'Foo');

It silly, but you could do it. However this is not really related to  
my point. The issue I am describing looks more like this in perl 5:


  package Hash;
  sub new { ... }
  sub keys { ... }
  sub values { ... }
  sub exists { ... }

  package Foo;

  sub new {
  my ($class, $hash) = @_;
  ($hash-isa(Hash)) || die hash needs to be an instance of Hash;
  bless($hash, $class);
  }

Why would you ever want to do such a think in Perl 5? So why would  
that be how bless works in Perl 6?


Stevan



Re: Perl 6's bless is (seriously) broken

2006-01-19 Thread Stevan Little

Juerd,

On Jan 19, 2006, at 4:21 PM, Juerd wrote:

Juerd skribis 2006-01-19 22:18 (+0100):

Could you live with @foo being an array, and @foo in scalar context
returning a reference to that array? And with arrays being  
interfaces to

underlying Arrays, which are objects, which makes arrays non-objects
that can be used *as* objects?


This turns everything is an object into everything can be used with
OO syntax, which I think is more true

Alternatively and simultaneously, everything represents an object.


Well, if everything is NOT an object, then the synopsis need to  
reflect this. I was under the impression that everything was an  
object, some of that object-ness is more hidden in some than  
others, but it does not mean they are not still objects.


My point though was not to debate OO theory, but to reconcile a  
problem in the Synopsis and it's description/usage of bless.  
Currently it is broken, and we need to fix it.


One fix, yes, is to say arrays and hashes are not objects, they are  
literals as in perl 5. Personally I am not sure that is a good  
approach, and seems to contradict more of the Synopsis then it agrees  
with.


Stevan



Re: Perl 6's bless is (seriously) broken

2006-01-19 Thread Stevan Little


On Jan 19, 2006, at 5:09 PM, Juerd wrote:

Stevan Little skribis 2006-01-19 17:06 (-0500):
This turns everything is an object into everything can be used  
with

OO syntax, which I think is more true
Alternatively and simultaneously, everything represents an object.

Well, if everything is NOT an object, then the synopsis need to
reflect this.


I was more thinking along the lines of NOT everything is an object,
but some things are.


sarcasm
Hmm, maybe we can add an Object context then. It would allow an  
something to be an object only when it is convienent for it to be so. ;)

/sarcasm

Stevan


Re: Perl 6's bless is (seriously) broken

2006-01-19 Thread Stevan Little


On Jan 19, 2006, at 5:19 PM, Jonathan Scott Duff wrote:

On Thu, Jan 19, 2006 at 11:07:49PM +0100, Juerd wrote:

Stevan Little skribis 2006-01-19 16:59 (-0500):

2) what if the role conflicts with other roles being does-ed by Foo?
Debugging hell there.


Very good point.


Aren't role conflicts resolved at composition time (possibly by
failure)?  That doesn't sound like debugging hell to me, but rather
clear indication of a problem and the location of that problem.


Role conflicts are resolved when a role (or set of roles) is composed  
into a class. In this case the (automatically generated) code would  
look something like this:


method new ($class: %params) {
my $self = $class.bless(%params);
$self does Hash;
return $self;
}

Or it would have to detect it in the class definition itself, in  
which case it would add a does Hash; to the class def somewhere.


The reason this would be debugging hell (IMO at least) is that *I*  
never told it to does Hash, so as far as I knew there was no clashes  
in the roles I composed. Sure if was educated in the finer points of  
Perl 6 I would know what happened, but a random newbie would be half- 
way to PHP by now.


Stevan



Re: Perl 6 OO and bless

2006-01-19 Thread Stevan Little

On 1/19/06, chromatic [EMAIL PROTECTED] wrote:

Next question.  If Ponie and Perl 6 are both running on Parrot, and  
if Ponie
has PMCs that represent Perl 5 data containers, such as p5hash,  
p5array,
p5symbol, and so on, what's the problem with having a Perl 6 object  
that uses

one of those PMCs as its internal storage?


Okay, so when you say alternate storage then you mean that a class  
like this:


class Foo {
has $.bar;
method new ($class, %params) {
$class.bless('p5Hash', %params);
}
method baz {
$.bar += 1;
}
}

should use a PMC representation of a p5 hash as it's storage, and  
that the method baz does the right thing here?


Because that makes sense to me. However, what doesn't make sense  
would be if I had to write baz like this:


method baz {
   self-{'bar'} += 1;
}

In other words, if this is just a detail of the storage, and does not  
affect user code at all, then I am okay with it. This though would  
mean that you would not have direct access to the underlying data  
structure (the p5 hash).


I realize one of Stevan's objections is But if you use a Hash,  
does your
object automatically support the .keys method and .kv and so on?  
to which I

reply No, of course not.  That's silly.  It just uses the Hash for
*storage*.


Okay, then I assume you mean it to behave the same way as with the  
p5hash, that it is completely transparent to the user that you are  
using a p5hash or a p6hash or a p6opaque?


In which case,.. I say okay. But note again that you have not  
provided access to the underlying data structure (the p6hash a.k.a -  
an instance of ^Hash).



Is that your objection to bless()?


Yes, that is my objection, because while the alternate storage  
approach discussed above is actually a very interesting feature, it  
does not fit with the p5 vision of bless.


With p5, you /can/ get to the underlying data structure. This is a  
break which will hamper the backwards compatibility effort I think.


I don't mean to handwave here -- there are definitely issues to  
consider when
crossing a language boundary related to method dispatch (and the  
last I
remember from design meetings was things change there and you  
shouldn't
expect that they stay the same), but the resistance to allowing  
different

storage types for objects completely baffles me.


Yes, this will be an interesting one :)

Or is the question about Why is there a need for bless() when you  
can already

pass arguments to CREATE()?  In that case I dunno.


Well as you say in your reply to Rob, TIMTOWTDI. I will agree with  
you here if they are in fact 2 ways to do the same thing. This would  
actually solve and simplify some issues in the metamodel currently.


And to be honest, I have absolutely no real objection to bless. I  
just don't think the current treatment of it is consistent with some  
of the stated goals of the Perl 6 design.


Stevan





Perl 6 OO and bless

2006-01-18 Thread Stevan Little

Hello All,

In reading over the Synopsis again in hopes of finding more  
information regarding the different repr types (see the warnocked  
post entitled Construction and Initialization of repr types other  
than P6opaque), I stumbled onto some issues with the Perl 6 OO model  
and bless.


In S02 it says:

Perl 6 is an OO engine, but you're not generally required to  
think in OO
when that's inconvenient. However, some built-in concepts such  
as filehandles

will be more object-oriented in a user-visible way than in Perl 5.

Now taking this statement one (logical) step further, and I assume  
that this means things like arrays and hashes will (underneath) just  
be objects. So we will have an ^Array class, and a ^Hash class, and  
[] and {} will actually construct instances of ^Array and ^Hash  
respectively. (Of course I am simplifying it here, these may be roles  
instead of classes, but this is not relevant to the discussion really).


Then later on S12 says:

As in Perl 5, a constructor is any routine that calls bless.  
Unlike in Perl 5,
you call it as a method on the class, passing the candidate as  
the first

argument. To bless a hash as in Perl 5, say:

$object = $class.bless({k1 = $v1, k2 = $v2, ...});

Are we not just re-blessing an instance of the class ^Hash into  
whatever $class is? That does not seem to be what is intended,  
however, if {} is a constructor for an instance of ^Hash, and I can  
call methods on {} like any other object ({}.keys, {}.exists($key),  
etc.), then what happens when I bless {} with a class? Do I loose  
access to the methods of ^Hash? Are the methods only allowed to be  
called in the non-invocant syntax (called like functions and not  
methods)?


Which brings me to my real question:

Do we really still need to retain the old Perl 5 version of bless?  
What purpose does it serve that p6opaque does not do in a better/ 
faster/cleaner way?


Thanks,

Stevan 


Re: Perl 6 OO and bless

2006-01-18 Thread Stevan Little

On 1/18/06, chromatic [EMAIL PROTECTED] wrote:

On Wednesday 18 January 2006 14:13, Stevan Little wrote:


Do we really still need to retain the old Perl 5 version of bless?
What purpose does it serve that p6opaque does not do in a better/
faster/cleaner way?


Interoperability with Perl 5 code.


How so? Please elaborate how you see this working?

Are you thinking that one would be able to bless a Perl 5 reference  
into a Perl 6 package?


I would argue then that we really don't need Perl 6 bless for this,  
and we can just use Perl 5's bless. After all, if Perl 5 can call  
Perl 6 functions, then Perl 5 will need to understand Perl 6's  
packages, and vice-versa. If this is true then Perl 5's bless should  
be able to accept a Perl 6 package value and DWIM. However, this  
would probably be a somewhat ugly solution to whatever problem it is  
you are trying to solve since your Perl 6 code would be weighted down  
with Perl 5 OO-isms. In fact, I would argue that doing it this way is  
not the right way, and instead using Perl 6 OO and delegating to a  
Perl 5 object is a better option.


Or are you thinking that a Perl 6 value should be blessed into a Perl  
5 package?


I think there is a real serious issue here since the hash the Perl 5  
package would be expecting is a ref to an HV, and the Perl 6 value it  
would be getting would be an instance of the ^Hash class (itself a  
subclass of ^Object). This is actually where i see the fundemental  
problem with a Perl 6 bless which is capable of blessing Perl 6  
references. There are no Perl 6 references like we had in Perl 5,  
they are *all* objects now. Would not the Perl 5 layer see the Perl 6  
instance of ^Hash as an object? If not, then we must already have a  
Perl 6 opaque (the ^Hash instance) to Perl 5 HV converter/proxy/magic- 
jellybean/thunk so I don't need to write it :)


Or maybe you are you thinking that a Perl 6 class can inherit from a  
Perl 5 class?


To be honest, i think this is better handled with delegation, and can  
even be automated using the attribute delegation features described  
in A/S12.


The biggest problem with this would be object initialization. The  
normal Perl 6 BUILDALL/BUILD code could not be used here since Perl 5  
does not have the meta-object protocol to support such behaviors, nor  
is there a common enough Perl 5 object initialization idiom to work  
with here. The end result is that you probably end up having to do a  
bunch of manual initialization code.


And let's not forget that our Perl 6 blessed hash is not the same as  
the Perl 5 blessed hash, so there might be confusion/issues there  
too. We also have the issue here of where does ^Object fit into our  
inheritance now? Is the Perl 5 package the top of our @ISA tree? or  
do we insert ^Object in there somewhere too?


Or maybe you are you thinking that a Perl 5 class can inherit from a  
Perl 6 class?


Well since Perl 5 inheritance is really just a package name in the  
@ISA, this is trivial to get method inheritance since Perl 5 already  
can understand Perl 6's packages. And lets assume that the Perl 5  
new uses the (somewhat common) idiom and just calls SUPER::new(@_)  
and re-blesses the returned Perl 6 instance. Let's assume too that  
the Perl 6 constructor just blessed a Perl 6 instance of ^Hash. Again  
we have the mismatch between the ref to an HV and the ref to an  
instance of ^Hash. This brings us back to our Perl 6 opaque (the  
^Hash instance) to Perl 5 HV converter/proxy/magic-jellybean/thunk  
thingy.


So in conclusion, I think that a Perl 6 bless which acts like a Perl  
5 bless is not as useful as your seem to indicate. It is certainly  
not the magic bullet of interoperability. I don't think we can really  
avoid not having a p6opaque-p5-blessed-ref magic-thunker.


However, maybe I am missing something here, if so, please elaborate  
and explain.


Thanks,

Stevan




Re: Perl 6 OO and bless

2006-01-18 Thread Stevan Little


On Jan 18, 2006, at 10:41 PM, Trey Harris wrote:
Excuse my ignorance of the finer points, but I thought the reason  
for bless's continued existence was so that the same sort of  
brilliant OO experimentation that Damian and others have done with  
pure Perl 5 can continue to be done in pure Perl 6 without having  
to hack p6opaque?


Actually bless only partially plays a role in all those whacky  
things which so many whacky people have done with Perl 5. Without  
AUTOLOAD, symbol table hacking and closures, bless would not be that  
exciting.


However, given a proper MOP (meta-object-protocol) the amount of  
Object Oriented experimentation which will be possible in Perl 6 will  
far exceed what you can do in Perl 5. Not to mention that it will  
also be type-safe and far more reliable (read: you could *actually*  
use it in production).


And not to put down all of the brilliant OO experimentation that has  
been done in Perl 5, but it is not always as cutting edge as one  
might think. A good amount of the really crazy cutting edge OO work  
is being done with either Smalltalk or CLOS and the fact they both  
have well defined and studied MOPs is probably a major reason for that.


Stevan 


S12: Possible contradiction in responsibilities of Class Object

2006-01-09 Thread Stevan Little

Hello all,

I have been reading the recently updated Synopsis 12, and a few  
things jumped out at me. In the Classes section, classes are  
described like this:


Classes are primarily for instance management, not code reuse.

Later in the same section the following is stated:

Every class is an instance of its metaclass. You can get at the  
metaclass of any object via the .meta method.


Later on in the Construction and Initialization section, the  
following comment is made:


All classes inherit a default Cnew constructor from CObject.

Now, making the assumption that instance management includes the  
creation of new instances, which I think is a reasonable assumption  
to make. It would seem that new should not be a method in Object,  
but instead a method of the class (aka - the MetaClass instance).  
This would then mean that MyClass.new() would be really mean  
MyClass.meta.new() (which is not without precedence since .isa  
and .can work the same way).


I would then describe Object's role in this as the initialization  
of new instances, as Object is where it makes the most sense for  
BUILDALL and BUILD to reside.


Stevan






Construction and Initialization of repr types other than P6opaque

2006-01-09 Thread Stevan Little

Hello again,

In Pugs, we are currently trying to figure out how classes are  
initialized with $repr types other than P6opaque. My interpretation  
of S12 is that P6opaque types are initialized as follows (by default):


new is called with named arguments, it then calls bless passing in  
'P6opaque' as the $repr type, and the named arguments after it.  
bless then calls CREATE, which constructs the opaque type using all  
the attributes of the class (which are collected in  
'descendent' (BUILD) order). At this point BUILDALL is called, which  
itself calls all the BUILD methods is can find (again in  
'descendent' order).


S12 lists several other $repr types which CREATE accepts such as  
P6hash, P5hash, P5array, PyDict  Cstruct. Some of these types are  
more conducive to construction in the manner in which CREATE  
constructs P6opaques. These seem to be separate from the $canidate  
argument for bless, which seems to work similar to how P5's bless  
worked.


So my question is: What is the purpose of the different $repr types?

Should the other $repr types be used in the same manner as P6opaque?  
Just alternate types of internal storage. Or should using these other  
$repr types act more like blessing these same/similar types (blessing  
a hash, blessing an array, etc).


Thanks,

Stevan







Re: Role Method Conflicts and Disambiguation

2005-11-03 Thread Stevan Little


On Nov 2, 2005, at 9:02 PM, Jonathan Lang wrote:

Let's say you have this:

  role A {method foo() { code1; } }
  role B {method foo() { code2; } }
  role C does A does B {
method foo() { A::foo(); }
method bar() { B::foo(); }
  }

Should the following be valid?

  role D does C { method foo() { B::foo(); } }

IMHO, it shouldn't, because D doesn't do B.


Not valid in what way? Should this be a fatal error?

Are you implying that B is not local to D, so it cannot use it? that  
somehow disambiguation must be done using one of your local subroles  
only?


I think this is too restrictive, D should be able to freely  
disambiguate or override using anything it want's to. It need not be  
related at all to it's subroles.


Stevan


Re: Why submethods

2005-10-29 Thread Stevan Little

Luke,

On Oct 29, 2005, at 3:42 PM, Luke Palmer wrote:
Another thing that scares me with the utility sub point of view  
follows:


class Foo {
method process_data($data) {
$.help_process_data($data);
}
submethod help_process_data($data) {
$data+1;
}
}

Foo.new.process_data(0); # 1

class Bar is Foo { }

Bar.new.process_data(0); # dies[1]

What???  I didn't change anything yet!  Why does it die?  (This is the
first principle in the journal entry you quoted)


This is true, but I think that it is easily rectified. A submethod is  
said to have an implicit


  next METHOD unless $?SELF.class =:= $?CLASS

I think we could add onto that and say that in addition to checking  
the invocant's class, we could also check the calling context, and do  
like we do with private methods, and allow things like this to Just  
Work.


However, it could also be that the creator of Foo did not intend for  
subclasses to be able to Just Work, and that the whole idea of Foo  
is to do a Template Method style pattern in which subclasses must  
implement the help_process_data submethod in order for things to  
work. This is an entirely valid usage for a submethod, and in fact, I  
think it is an excellent way for implementing the Template Method  
pattern.


It is also possible that we could bring over the role idea of  
required methods and have the same basic principle relate to  
classes and submethods. If marked as such, a submethod is required to  
be implemented by a subclass, or class composition fails. I think  
that could be a useful feature which would allow very safe re-use  
along those lines.


Anyway, just my 2 cents.

Stevan



Re: Role Method Conflicts and Disambiguation

2005-10-28 Thread Stevan Little

Yuval,

On Oct 28, 2005, at 10:59 AM, Yuval Kogman wrote:

On Thu, Oct 27, 2005 at 22:19:16 -0400, Stevan Little wrote:
Now, at this point we have a method conflict in suspension since   
(according to A/S-12) method conflicts do
not throw an error until a  role is composed into a class. This  
means that when I do this:


class MyClass does FooBar {}

an exception is thrown. Unless of course MyClass has a foo  
method,  which will disambiguate the conflict.
My question then is, can FooBar  (the role) disambiguate the foo  
conflict?




IMHO yes, but it doesn't have too. It should be able to leave it to
the class to decide.


If we allow the class to decide if things break or not, then we  
potentially allow for the system to be in a very unstable state. A  
method conflict means that neither method gets consumed, and at that  
point we have a gapping hole in our class. IMHO we should not allow  
this to be decided by the user in any other way then to  
disambiguate,.. otherwise we should die very loudly.


In the end, we will have probably looked inside every method  
defined  in Foo, Bar, FooBar and Baz in order
to properly write MyClass2.  IMHO, this is sort of defeating the  
usefulness of roles at this point.




I disagree - you have to know what a role is actually giving you to
exploit it. Too much black boxing makes your programming language
seem like a Kafka story.


Why? does it introduce bugs? ;-P


So what do you all think??


Role method conflicts should only be dealt with if the user knows
what the roles are actually doing anyway. This will probably be
familiar code, and if not it warrants familiarity.


Agreed.


I don't think we can let the user use library code without being
aware of the library code internals at all. Abstraction that works
like this is usually either crippled or useless. 90% of the time you
don't want to know, but there are exceptions.


A little extreme, but I tend to agree with your point.

Stevan



Re: Role Method Conflicts and Disambiguation

2005-10-28 Thread Stevan Little


On Oct 28, 2005, at 11:17 AM, Jonathan Scott Duff wrote:

On Thu, Oct 27, 2005 at 10:19:16PM -0400, Stevan Little wrote:


I have a question about method conflict resolution works for roles,
and I cannot seem to find this in any of the Apoc/Syn documents.

Here is the basic issue:

role Foo {
method foo { ... }
method bar { ... }  # we will use this later :)
}

role Bar {
method foo { ... }
}

role FooBar {
does Foo;
does Bar;
}

Now, at this point we have a method conflict in suspension since
(according to A/S-12) method conflicts do not throw an error until a
role is composed into a class. This means that when I do this:



If we say that the roles Foo and Bar are composed into the role
FooBar and that method conflicts trigger an exception at composition
time (whether composed into a role or class), then your above
declaration of FooBar will trigger an exception and force the user to
resolve the conflict.


Well, if we allow FooBar to die, then we do not allow for possible  
disambiguation by a class (which is the only place it matters anyway  
since roles cannot be directly instantiated). I think that not  
keeping the conflict in suspension until the role is composed will  
actually restrict the usefulness of roles. I should be allowed to  
create a role with all sorts of conflicts which I leave for the  
classes to deal with.


Remember that if you create a role with a stub method (method my_stub  
{ ... }) then it acts just like a conflict does in requiring the  
consuming class to implement it.


Stevan



Re: Role Method Conflicts and Disambiguation

2005-10-28 Thread Stevan Little


On Oct 28, 2005, at 11:38 AM, Jonathan Scott Duff wrote:

On Fri, Oct 28, 2005 at 04:59:18PM +0200, Yuval Kogman wrote:


If, OTOH we have a diamond inheritence:


You mean composition.  There is no role inheritance  :)


role A { method foo { ... } }
role B does A {};
role C does A {};
class D does A does B { };


I'm assuming you meant

class D does B does C { ... }


I'm not sure we need to resolve the conflict.


It depends on when composition happens. If A is composed immediately
into B and C as soon as the role is processed, then when D is being
composed, all it sees are a foo method from the B role and a foo  
method

from the C role.

If, however, roles aren't composed into other roles but only into
classes, then I think that

class D does B does C { ... }

would be equivalent to

class D does A does B does C { ... }

since the roles B and C would carry the uncomposed A role along with
them.


Personally, I think the later makes the most sense. This fits very  
well with the roles are just containers idea. A role flattens  
method, attributes, *and* subroles too.



If, on the other hand, we have

role X trusts Foo does Foo {
has $:foo;
}



Quoth A12:

It's not clear whether roles should be allowed to grant trust. In
the absence of evidence to the contrary, I'm inclined to say  
not. We
can always relax that later if, after many large, longitudinal,  
double-

blind studies, it turns out to be both safe and effective.

Has that changed?


To quote $Larry[0] A12 should be read for entertainment purposes only

I know, that scares me too ;)


Stevan


Re: Role Method Conflicts and Disambiguation

2005-10-28 Thread Stevan Little


On Oct 28, 2005, at 2:54 PM, Jonathan Scott Duff wrote:

On Fri, Oct 28, 2005 at 02:29:36PM -0400, Stevan Little wrote:
I should be allowed to create a role with all sorts of conflicts  
which

I leave for the classes to deal with.


Er, why? I've read this sentence several times and I'm really having
trouble grasping why anyone would deliberately create a conflicted  
role

and want to postpone the conflict resolution until later.


Well, certain classes might want to deal with the conflict in certain  
ways.


role Foo {
method foo { [ 1, 2, 3 ] }
}

role Bar {
method foo { { one = 1, two = 2, three = 3 } }
}

role FooBar {
does Foo; does Bar;
method display_foo {
self.foo.values.join(', ');
}
}

class MyFooArray does FooBar {
foo := Foo::foo;
}

class MyFooHash does FooBar {
foo := Bar::foo;
}

The conflict here basically allows the user of FooBar to determine  
what kind of data structure to use, while also providing basic means  
of displaying the data structure. The example a little contrived, but  
it might be a useful technique in some areas.



It seems to me
that conflicts should be resolved sooner rather than later. Especially
in the light of run-time composition:

role A { method foo { ... } ... }
role B { method foo { ... } ... }
role C does B does A { ... }
my Dog $spot;
...
$spot does C;


Well why should this be any less dangerous that this:

my $spot = (class { does A; does B; }).new();

Which is what it will be desugared into anyway.

It might also be possible for the compiler to catch this kind of  
stuff too.



Would you rather wait until perl is actually executing that last line
of code before finding out there's a conflict or would you rather know
there's a conflict at compile-time (when C is immediately composed of
A and B)?


To be totally honest, I think if you do runtime role composition with  
a role which you know has a conflict (I mean I assume you either  
created that role, or know what it provides before you use it), then  
you deserve all the pain and suffering associated with it.



Yes, I realize that Perl6 already has the problem that run-time
composition could cause conflicts, but I want to have a slightly
smaller chance of running into it :)


Actually, according to the for entertainment purposes only A12, if  
I do this:


$spot does Dog does Cat;

I am really doing this:

$spot = (class { is (class { does Dog; }); does Cat; }).new();

So it won't actually conflict.

Stevan





Re: Role Method Conflicts and Disambiguation

2005-10-28 Thread Stevan Little


On Oct 28, 2005, at 3:04 PM, Jonathan Scott Duff wrote:

But, I'm probably wrong about this as the X role may have methods that
use $:foo in one way and the Y role may have methods that use $:foo in
some other, incompatible way, so perhaps there will be a conflict just
as when there are 2 methods of the same name.


Yes, they have to conflict. Attribute conflict rules should be the  
same as method conflict rules.


Stevan


Re: Role Method Conflicts and Disambiguation

2005-10-28 Thread Stevan Little


On Oct 28, 2005, at 3:45 PM, Rob Kinyon wrote:

Doing it any other way leads to the following: if A does rA and B isa
A and B defines an attribute that conflicts with the one provided by
rA, how on earth is that supposed to be detected? Especially given
that the inheritance tree of a class can be modified at runtime.


B should not know or care that A does rA, because by the time B gets  
to A, rA has already been consumed by A.


If B does not want it's attributes to conflict,.. make 'em private.  
If rA is concerned that it's attributes will get mussed with, it  
should make 'em private too (which IMO would mean that A gets a new  
private attribute, not that it is privatet to the role).


Your method (as we have discussed in the past) means that Roles now  
have instance specific data, which needs to be stored somewhere,  
somehow (not too difficult). And our class now needs to keep  
information about the roles it composed around so that it can  
dispatch to methods appropriately (also not too bad). This then means  
that the method dispatcher, when it cannot find a private method  
locally, needs to check all the roles which were composed into the  
class to find the correct private method and then call that method (I  
assuming no method conflicts here, but they can (and will) happen).  
The method then needs to be able to find and extract the role  
specific private instance data (this action itself requires some  
complex access control checks), and then do something with it.


Like I said, this is assuming we have no conflicts, because the  
dispatcher will have a hard time determining which role specific  
private method named :foo you mean in the context this is all  
happening in. And if we check for conflicts up front, we start to run  
into the same issues that we did before.


One possible solution might be to only allow methods defined within  
the role to access the private role methods. But then what happens if  
that method is in conflict. Here is an example:


role Foo {
has $:bar; # this is role private data
method :get_bar { $:bar } # a role private method

method gimme_bar { self.:get_bar() } # the public face to the  
private role data

}

class Blah does Foo {
method gimme_bar { ... }
}

At this point :get_bar and $:bar are totally inaccessible.

IMO, roles should be just containers, and they should hand over  
everything they have to the class they are composed into. I also  
think Subclasses should not care what roles their superclasses  
consumed, that is personal information for the class only to know.


Stevan




Re: Role Method Conflicts and Disambiguation (Theory-theoretic take)

2005-10-28 Thread Stevan Little

Luke,

On Oct 28, 2005, at 9:44 PM, Luke Palmer wrote:

It was the fact that at each stage of the game, we summarized the
defaults and requirements for each role, ignoring the internal makeup
(i.e., what roles were composed into it, etc.).


This then imposes somewhat of an ordering with role composition. The  
role tree will need to be traversed breadth first, and conflicts/ 
requirements resolved on a level by level basis.



And it sounds correct to me.


It sounds correct to me as well (in theory,.. get it ,... in  
theory :P).


However, I do worry about how it will work out in practice. Part of  
the goal of roles (and I have been preaching this one since the  
hackathon) is that they are easier to use than multiple inheritance,  
have fewer headaches than mix-ins and are more useful than  
interfaces. Imposing ordering as described above may make things  
easier, or it may make things harder, only time and experience will  
tell. I am going to give this some more thought over the weekend, and  
see what I come up with.


Stevan


Role Method Conflicts and Disambiguation

2005-10-27 Thread Stevan Little

Hello all,

I have a question about method conflict resolution works for roles,  
and I cannot seem to find this in any of the Apoc/Syn documents.


Here is the basic issue:

role Foo {
method foo { ... }
method bar { ... }  # we will use this later :)
}

role Bar {
method foo { ... }
}

role FooBar {
does Foo;
does Bar;
}

Now, at this point we have a method conflict in suspension since  
(according to A/S-12) method conflicts do not throw an error until a  
role is composed into a class. This means that when I do this:


class MyClass does FooBar {}

an exception is thrown. Unless of course MyClass has a foo method,  
which will disambiguate the conflict. My question then is, can FooBar  
(the role) disambiguate the foo conflict?


role FooBar {
does Foo;
does Bar;
method foo { ... }
}

Now, on the surface this seems obvious, of course the FooBar role  
should be able to disambiguate. However, when we expand the example  
other issues show up.


role Baz {
does Foo;
}

class MyClass2 does FooBar does Baz {}  # Will this die?

Now, since MyClass2 actually does Foo twice, does that mean bar  
creates a conflcit? Since bar would be found through FooBar and Baz.  
I would think the answer here would be no, and that we would build  
some kind of unique list of roles so as to avoid repeated consumption  
like this.


But thats not all, we have a potential problem with foo again. Baz  
will provide foo from Foo, but FooBar will provide it's own foo  
(which we used to disambiguate). So our disambiguation is not  
ambiguated again.


/ Possible Solutions /

A (deceptively) simple solution to this is that MyClass2 needs to  
disambiguate. But this means that our roles are not really black  
boxes anymore. In order to properly disambiguate this we need to know  
where all the foo methods are coming from (Foo, Bar and FooBar), and  
potentially what is inside these foo methods (especially in the case  
of FooBar since it is attempting to disambiguate, it's behavior could  
be very specific). It probably would also become important to know  
what other methods foo interacts with since we potentially have 3  
different expected versions of foo.


In the end, we will have probably looked inside every method defined  
in Foo, Bar, FooBar and Baz in order to properly write MyClass2.  
IMHO, this is sort of defeating the usefulness of roles at this point.


Another simple (but maybe slightly unintuitive) solution would be to  
not allow roles to disambiguate at all.


(Quick side note: Doing this means that roles like FooBar (which  
carry with them a suspended conflict) would be restricted in what  
types of behaviors they can provide. Basically they would only be  
able to provide new behaviors which are unrelated to those provided  
by Foo and Bar. If it were to try to use methods from Foo or Bar, it  
would really end up needing to disambiguate.)


This actually makes MyClass2 somewhat simpler now, since it only need  
to disambiguate between foo from Foo, and foo from Bar. Of course  
this is only marginally better, since you would still need to look  
inside all the methods of Foo, Bar, FooBar and Baz to see how foo is  
being used so you could disambiguate properly.


...

So what do you all think??

Stevan






Re: Ways to add behavior

2005-10-26 Thread Stevan Little


On Oct 26, 2005, at 12:05 PM, Larry Wall wrote:

Of course, there are other words that are somewhat synonymous with
class, Unfortunately sort is already hosed.  Maybe kind.


Actually kind is used in the Core Calculus for Metaclasses paper  
which I brought to the hackathon (not sure if you got to read it or  
not). Here is a link:


http://research.sun.com/projects/plrg/core-calculus.pdf

They present an rather interesting view on things, that the  
definition of the instance creating portion of a class should be  
seperated from the class or kind portion of the class. Actually  
the first metamodel prototype grew out of an implementation of the  
model they describe in the paper.


Stevan


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: Ways to add behavior

2005-10-25 Thread Stevan Little

Larry,

On Oct 25, 2005, at 4:37 PM, Larry Wall wrote:

On Mon, Oct 24, 2005 at 06:33:20AM -0700, Ashley Winters wrote:
: # behavior through prototype -- guessing realistic syntax
: Base.meta.add_method(
: do_it = method ($arg) {
: say doing $arg!;
: });
:
:
: # or, just add it to a single instance
: $x.meta.add_method(
: do_it = method ($arg) {
: say doing $arg!;
: });

I don't have a comment on your actual question, but I'd like to use
this opportunity to point out the symmetry of Base and $x at this
point, and the fact that .meta can't simply call .add_method in the
metaclass, or it would lose track of the original invocant, which is
needed to convey both class and instance information.  I'm not sure
it's even possible to say

$m = $x.meta;
$m.addmethod($arg);

The only way that can work is if $x.meta returns a shadow class that
is prebound only to $x.  (Though that might explain how .addmethod
knows it's only adding a method to the object.)


This is actually the principe behind the Ruby style singleton methods  
(the shadow class), it basically creates an anon-class which inherits  
from $x's original class, then it rebinds/blesses $x into the anon- 
class. It is very simple really :)


As for if this is/should be accessible through .meta, i am not sure  
that is a good idea. The reason being is that .meta brings with it  
the idea of metaclasses, which then relates to classes, and so now  
the user is thinking they are accessing the metaclass of the class of  
which $x is an instance.


I would suggest instead that we have a method, which is found in  
Object which allows instances to add methods to themselves (and only  
themselves). In Ruby this is called 'add_singleton_method' or  
something like that. I use that same name in the metamodel prototype  
too.



In the absence of that, what's going on seems more like

$x.META::addmethod($arg);

where META:: is smart enough to dispatch to the proper metaclass  
without

throwing away the invocant, and then the metaclass decides what to do
based on the instancehood of $x.


I am not sure I like this for 2 reasons.

1) META:: smells like ::SUPER, and that feels like re-dispatching to  
me, which is not really what we need to be doing.


2) there is not need to send this back to the metaclass level. The  
whole thing could be accomplished as an instance method of Object.  
Here is how it could be done.


class ShadowClass does Class {}

class Object is reopened {
method add_singleton_method (Str $label, Method $method) {
if ($?SELF.class.class != ShadowClass) {
my $shadow = ShadowClass.new();
$shadow.meta.superclasses([ $shadow ]);
$?SELF.class = $shadow;
}
$?SELF.class.meta.add_method($label, $method);
}
}

Stevan





Re: syntax for accessing multiple versions of a module

2005-10-19 Thread Stevan Little

Larry,

On Oct 19, 2005, at 4:10 AM, Larry Wall wrote:

On Tue, Oct 18, 2005 at 07:38:19PM -0400, Stevan Little wrote:
: Then this is added as Dog-0.0.2-cpan:LWALL into the main symbol
: table. Then once the compilation process is complete, I traverse the
: symbol table hierarchy collecting all the names. Any duplicate short
: names (Dog) are noted for later. Once I have collected all the  
names,

: I build all my aliases.
:
: So if I find:
:
:   use Cat-0.0.1-cpan:JRANDOM;
:
: only once, I build an alias for (at a minimum) Cat and  
Cat-0.0.1.


But you have to have the aliases there for correct parsing.  Otherwise
Cat is a bareword, which is illegal. Of course, you can add the
alias without deciding what to bind it to.  In fact, within a method,
we require Cat to be considered a virtual name, so if a derived
class uses a different Cat, it means that one instead for this object.


I suppose this could be done earlier in the compilation process then,  
possibly we can make assumptions along the way and alias short names  
immediately, only to retract the alias later if we see something that  
conflicts. Assuming we do not encounter any user-level aliasing, I  
think this would probably be okay.


However, this brings up an issue I was thinking about. Take this code  
for instance:


  use Cat-0.0.1;
  use PetStore;

  my Cat $kitty .= new();

--- in PetStore.pm ---

  use Dog;
  use Cat-0.0.5;

Which Cat is used? I can see several options:

1) Cat-0.0.1 is used since it is in the local scope, so clearly the  
users choice.


2) Cat-0.0.5 is used since it is loaded after Cat-0.0.1.

3) An Ambiguity error is thrown because Cat is not specific enough.

Any option other than 1 requires the user to know what is going on  
within PetStore.



: For my duplicates, the table would look something like this I think:
:
:   Dog   = Dog-1.2.1-cpan:JRANDOM
:   Dog-1.2.1 = Dog-1.2.1-cpan:JRANDOM
:   Dog-0.0.2 = Dog-0.0.2-cpan:LWALL
:
: We are explictly giving the preference to the later version  
number (I

: think we discussed this at the Toronto hackathon).

Hmm, don't remember that.  But I have a bad memory.


To be honest, I am not sure who I discussed it with, it might have  
been autrijus. Either way it was in the early days of the hackathon,  
and being a not-so-exciting topic, it was quickly forgotten about for  
much cooler topics :)


To be honest, I don't really like this approach anyway.


: Another school of thought would be that Dog alone would be
: considered ambiguious and so we would just alias far enough to be
: clear, like this:
:
:   Dog   = Ambiguity Error!
:   Dog-1.2.1 = Dog-1.2.1-cpan:JRANDOM
:   Dog-0.0.2 = Dog-0.0.2-cpan:LWALL
:
: Of course, this means that if I also load Dog-1.2.1-cpan:LWALL  
that

: the table looks like this:
:
:   Dog   = Ambiguity Error!
:   Dog-1.2.1 = Ambiguity Error!
:   Dog-0.0.2 = Dog-0.0.2-cpan:LWALL
:
: And the user is now forced to add the cpan id to get Dog-1.2.1. I am
: not sure how strict @Larry wants this to be.

I think $Larry wants to be strict on this, at least this week.


Horray!

If you're using two different versions explicitly within the same  
scope, you should
probably be required to alias one of them.  The main purpose of  
version

co-existence is for different modules to use different versions, not
the same module.  I think using two different versions from the same
module is going to be relatively rare.


Well, the first thing that comes to mind is that you could create a  
best-of-both-worlds proxy object/module. Say some insane CPAN  
developer radically changes an API, some of the changes make senses,  
some of the changes clearly illustrate the developers insanity. It  
might be useful to be able to create some kind of mix-up of the two  
module versions in which you alias part of each API (assuming they  
can co-exist peacefully that is).


Sure it's an out-on-the-edge case, but I could see some possible  
usefulness.


Stevan




Re: subclassing associated classes elegantly

2005-10-19 Thread Stevan Little

Darren,

Your problem reminds me of the Expression Problem, which is  
something that IIRC Luke's Theory idea was trying to solve. Here is  
the link to a paper Luke referred me to on the subject:


http://scala.epfl.ch/docu/files/IC_TECH_REPORT_200433.pdf

Also, you can Google the phrase Expression Problem and find quite a  
bit on the subject.


Stevan

On Oct 19, 2005, at 6:11 PM, Darren Duncan wrote:

I'm in a long-standing situation with my module development where I  
want to design a set of associated classes such that invocations of  
submethods or class methods, such as new(), of one class by another  
class continue to work as expected when any or all of those classes  
is subclassed.  I have a solution already that works, but I'm  
looking for the most optimal solution.


An example of when this situation can arise is if person X  
implements a simplified XML DOM implementation using 2 classes,  
Document and Node, that work together, where one of those classes  
(Document) can create objects of the other (Node), and person Y  
wants to subclass the XML DOM implementation, meaning that those  
same Node objects made by one of person Y's Document subclass  
should be objects of person Y's Node subclass.


To illustrate, say we had these 4 classes (the syntax may be wrong):

  # This is one associated class set:

  class A {
submethod one () {
  return 'hello';
}

submethod two () {
  B.four();
}
  }

  class B {
submethod three () {
  A.one();
}

submethod four () {
  return 'here';
}
  }

  # This is separate and optional associated class set:

  class C is A {
submethod one () {
  return 'world';
}
  }

  class D is B {
submethod four () {
  return 'there';
}
  }

What I want to be able to do is set things up so that user code can  
do something that is effectively like this:


  my $first = A.two(); # returns 'here'
  my $second = B.three(); # returns 'hello'
  my $first = C.two(); # returns 'there'
  my $second = D.three(); # returns 'world'

The situation is that classes C and D represent any arbitrary named  
2 classes that are subclassed from A and B, and so the latter can't  
know the names of the former, and the latter have to work  
independently of C and D also.


This is one variant of a solution I have come up with:

  # This is one associated class set:

  role AB {
submethod name_of_class_A () {
  return 'A';
}

submethod name_of_class_B () {
  return 'B';
}
  }

  class A does AB {
submethod one () {
  return 'hello';
}

submethod two () {
  .name_of_class_B().four();
}
  }

  class B does AB {
submethod three () {
  .name_of_class_A().one();
}

submethod four () {
  return 'here';
}
  }

  # This is separate and optional associated class set:

  role CD {
submethod name_of_class_A () {
  return 'C';
}

submethod name_of_class_B () {
  return 'D';
}
  }

  class C is A does CD {
submethod one () {
  return 'world';
}
  }

  class D is B does CD {
submethod four () {
  return 'there';
}
  }

This is another variant of a solution I have come up with:

  # This is one associated class set:

  role AB {
submethod invoke_one () {
  return A.one();
}

submethod invoke_four () {
  return B.four();
}
  }

  class A does AB {
submethod one () {
  return 'hello';
}

submethod two () {
  .invoke_four();
}
  }

  class B does AB {
submethod three () {
  .invoke_one();
}

submethod four () {
  return 'here';
}
  }

  # This is separate and optional associated class set:

  role CD {
submethod invoke_one () {
  return C.one();
}

submethod invoke_four () {
  return D.four();
}
  }

  class C is A does CD {
submethod one () {
  return 'world';
}
  }

  class D is B does CD {
submethod four () {
  return 'there';
}
  }

In either case, the expectation here is that the submethods of role  
CD will override those of role BC regardless of which class' other  
methods invoke those, when the invocant class is C or D.


So I'm wondering what is the best way to develop my associated  
class sets such that it is easiest for third parties to be able to  
subclass-extend them.  Should I use one of the two solutions above  
(both of which have been tried in real life, in Perl 5, the second  
more recently)?  Or is there another solution that is better than  
both?


Also, in such a situation as the above, is it reasonable to support  
easy subclassing, or would it be better to avoid that complexity  
and instead expect users to create objects that wrap the others  
instead of subclassing them?


Assume also that it may be counter-productive for one class to  
expect user code to invoke the second class on its behalf, such as  
if when pair of classes is hidden behind a second pair of classes  
that 

Re: top 5 list needed

2005-10-18 Thread Stevan Little

Uri,

Well, aside from what is actually *in* Perl 6 currently, there are a  
number of interesting side projects, which may or may not get  
included in the final language design. Such as:


On Oct 18, 2005, at 3:40 AM, Uri Guttman wrote:

the new OO design (stole the best from the rest and perlized it)


The current object model prototype (not yet totally approved) is a  
self-bootstrapping meta-circular object model which is heavily  
influenced by the CLOS Meta Object Protocol and Smalltalk. It  
includes several features which are not found in any of your  
traditional OO languages, such as Roles (which are a descendent of  
Traits, I could site some papers here is this would help).


You might also want to include Luke Palmer's current work on  
Attribute Grammars and the Theory model. Both of these are very  
Haskell-ish. I will let Luke speak about those.


Yuval Kogman's recent Exceptuation proposal (the marriage of  
exceptions and continuations, this exceptions you can *actuallY*  
recover from) is very similar to the condition system of Common LISP.


There has also been much work on a type inferencing system for Perl 6  
(type *checking* if just old-skool, all the cool kids infer).


The fact Pugs is written in Haskell (a language only a professor  
could love) might be a help.


There is also the new Perl 6 packaging system. It will be far more  
complex than the Perl 5 one, since it will not only include the 3  
part name (Foo-0.0.1-cpan:JRANDOM), but it will probably need to  
support seperate compilation units as well. This is borrowed from  
everywhere, but specifically we have looked at Fortress (the new  
scientific progamming language from Sun) and the new .NET assembly  
model.


Thats about all I can think of now.

Stevan





Re: top 5 list needed

2005-10-18 Thread Stevan Little


On Oct 18, 2005, at 1:45 PM, Luke Palmer wrote:


On 10/18/05, Rob Kinyon [EMAIL PROTECTED] wrote:


3) Macros. Nuff said.



Not quite.  Lispish macros, that is, macros that let you look at what
you're expanding.


To further expand on this, they will be AST-manipulating macros (LISP  
style) rather than text-replacing macros (C style).


Stevan


Re: syntax for accessing multiple versions of a module

2005-10-18 Thread Stevan Little

Nicholas,

This is addressed in S11, here is a link:

  http://search.cpan.org/~ingy/Perl6-Bible/lib/Perl6/Bible/S11.pod

To summarize, the syntax to load the modules is:

  use Dog-1.2.1;

While the syntax to create a specific version of a module is:

  my Dog-1.3.4-cpan:JRANDOM $spot .= new(woof);

I addresses the class creation syntax partially in the initial  
version of the Metamodel prototype, which was built in p5. I  
basically just aliased the package with the long name (%{Dog-1.3.4- 
cpan:JRANDOM::} = %{Dog::}). However this does no good for loading  
of modules.


I have been giving this some though though, and here is a rough  
sketch of what I have come up with so far.


Any module loaded is stored into *:: (or the p5 *main::) as the  
longest name given. This means that if I do this:


 use Dog-1.2.1-cpan:JRANDOM;

Then I have an entry for Dog-1.2.1-cpan:JRANDOM in the symbol  
table. If, further along in the compilation process, I encounter  
another Dog, such as:


 use Dog-0.0.2-cpan:LWALL;

Then this is added as Dog-0.0.2-cpan:LWALL into the main symbol  
table. Then once the compilation process is complete, I traverse the  
symbol table hierarchy collecting all the names. Any duplicate short  
names (Dog) are noted for later. Once I have collected all the names,  
I build all my aliases.


So if I find:

  use Cat-0.0.1-cpan:JRANDOM;

only once, I build an alias for (at a minimum) Cat and Cat-0.0.1.  
For my duplicates, the table would look something like this I think:


  Dog   = Dog-1.2.1-cpan:JRANDOM
  Dog-1.2.1 = Dog-1.2.1-cpan:JRANDOM
  Dog-0.0.2 = Dog-0.0.2-cpan:LWALL

We are explictly giving the preference to the later version number (I  
think we discussed this at the Toronto hackathon).


Another school of thought would be that Dog alone would be  
considered ambiguious and so we would just alias far enough to be  
clear, like this:


  Dog   = Ambiguity Error!
  Dog-1.2.1 = Dog-1.2.1-cpan:JRANDOM
  Dog-0.0.2 = Dog-0.0.2-cpan:LWALL

Of course, this means that if I also load Dog-1.2.1-cpan:LWALL that  
the table looks like this:


  Dog   = Ambiguity Error!
  Dog-1.2.1 = Ambiguity Error!
  Dog-0.0.2 = Dog-0.0.2-cpan:LWALL

And the user is now forced to add the cpan id to get Dog-1.2.1. I am  
not sure how strict @Larry wants this to be.


I have been meaning to do some kind of p5 prototype of this, I can  
push it up the TODO list if it would help you.


Stevan

On Oct 18, 2005, at 5:41 PM, Nicholas Clark wrote:


Sorry if I'm asking a question that I've missed in a synopsis.

Perl 6 will be able to load more than one version of the same  
module.

As I understand it, this would let you have more than one version of
DBI loaded in the same interpreter, and also have DBI written by  
Tim Bunce

and DBI written by A.U.Thor in the same interpreter.

Is the syntax for accessing different versions of the same module  
from Perl

nailed down yet?

Specifically this is in reference to wondering if the multiple  
module trick

would actually be possible in perl 5:

http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2005-10/ 
msg00585.html


and how to do something functionally like:

  my $foo = DBI(1.38)-new();
  my $bar = DBI(1.40)-new();

or whatever to distinguish which you wanted to call a class method on.

Nicholas Clark






Re: Re(vised): Proposal to make class method non-inheritable

2005-10-17 Thread Stevan Little

Miroslav

On Oct 17, 2005, at 7:35 AM, Miroslav Silovic wrote:

[EMAIL PROTECTED] wrote:
I think what bothers me most about this is that it seems there is  
no  way to tell the difference between class methods and instance   
methods. That the distinction is only made when the body of the   
method does something which is is not supposed to do (method  
called  with a class invocant attempts to access an instance  
variable, etc).


This is one of the major problems that I have always had with Perl  
5  OO. That there is a very fuzzy fuzzy line between the   
responsibilities of a class and an instance.


I can see the notion of a class which is not yet instantiated,  
this  makes sense in many contexts. But I don't think that in  
order to have  this, we need to bring back this element of Perl 5  
OO. I think we can  still have all the behaviors you have been  
describing, and still keep  classes and their instances as  
distinct entities.




It just recently occured to me that Class is a Package.


Actually, to be precise, Class is a Module, and Module is a Package.  
Modules add the version and authority portions to the name of a  
Package, and it seems that exporting (as traits?) are Module things,  
and not Package things.


So, on the object model level, class methods/attributes belong to  
the Package part of a class, while instance methods/attributes  
belong to the Class part of a class - insofar as they're made  
distinct by use of my/our.


Well, currently in the prototype, class attributes defined with our  
are stored in the Classes symbol table (which is inherited from  
Package). Discussions with autrijus lead me to not address class  
attributes defined by my, since he felt they would be better  
addressed as normal variables within the scope of the class body.  
This is somewhat of an implementation detail, however, I think it may  
also play a part in how these things work. For instance, in the  
following example, is $.foo a class attribute? or just a local  
variable for the inner block?


class Bar {
our $.bar;
{
my $.foo;
}
}

I assume that the leading $. is what makes the difference, however,  
IIRC the $. is just part of the name, and no more special than  
that. Which means that I can choose that name (yes, it is evil, but I  
assume I can still do it).


But given that the variable will be accessible to all methods via the  
closure mechanism, the only thing missing I think is the ability to  
get at the variable via introspection.


Now, as for class methods, I suppose it is possible to just stash  
then in the classes symbol table like with variables. However, do we  
then loose the method call syntax? This also means that they would  
not (directly) be inheritable since inheritence moves along  
superclass lines, and not with @ISA. I am also not sure what you mean  
about multi-methods either, could you please explain more?


Thanks,

Stevan






Re: Re(vised): Proposal to make class method non-inheritable

2005-10-15 Thread Stevan Little

Larry,

On Oct 14, 2005, at 2:15 PM, Larry Wall wrote:

Look guys, I want it to just consistently be

method bark (Dog $d) {...}

regardless of how instantiated the dog is.  Think of partially
instantiated subroutines via .assuming.  A sub is a sub regardless of
how much it's been curried.  So who cares if it's a complete Dog or
a partial Dog, or a completely generic Dog?  Nobody cares until you
try to call a specific method that relies on some specific attribute.
If you call a sub with an incomplete definition, you should be  
prepared
to handle the exception.  If you call a method with an incomplete  
object,

you should be prepared to handle the exception.

Of course, by that argument, $d should be considered defined even if
it's a completely uninstantiated class object.  With subs the final
proof of actual well-definedness (not to be confused with .defined())
is whether it can be bound to a particular set of arguments.  It's a
rather lazy definition of well-definedness.  I'm proposing that
all objects follow the same model of not caring how well they're
defined until you actually try to use them for something.  I don't
think I care any more about whether classes test as defined or not.
It's like reality--there are a lot of complex problems where the
simplest way to simulate them is via reality itself, and all other
simulations are guaranteed to be slower.


I think what bothers me most about this is that it seems there is no  
way to tell the difference between class methods and instance  
methods. That the distinction is only made when the body of the  
method does something which is is not supposed to do (method called  
with a class invocant attempts to access an instance variable, etc).


This is one of the major problems that I have always had with Perl 5  
OO. That there is a very fuzzy fuzzy line between the  
responsibilities of a class and an instance.


I can see the notion of a class which is not yet instantiated, this  
makes sense in many contexts. But I don't think that in order to have  
this, we need to bring back this element of Perl 5 OO. I think we can  
still have all the behaviors you have been describing, and still keep  
classes and their instances as distinct entities.



But we have to think a bit more about the notion of currying class
objects into real objects, or something approaching real objects.


This is an interesting thought, I will have to ponder it some, but it  
has a nice smell. Of course I love indian food and functional  
programming, so that may be personal bias :)


Stevan



Re: Re(vised): Proposal to make class method non-inheritable

2005-10-15 Thread Stevan Little

Larry,

On Oct 15, 2005, at 11:25 AM, Larry Wall wrote:

: But we have to think a bit more about the notion of currying class
: objects into real objects, or something approaching real objects.
:
: This is an interesting thought, I will have to ponder it some,  
but it

: has a nice smell. Of course I love indian food and functional
: programming, so that may be personal bias :)

Could turn out that $obj.assuming is just a generalization of
func.assuming.  That'd be kinda cool.


What would be in the other side of $obj.assuming?

Assuming $obj is an instance already, what are we creating with it?

Or perhaps you mean Object.assuming()?

In which case it would produce some partially instantiated class.

Please clarify :)

Stevan




Re: Re(vised): Proposal to make class method non-inheritable

2005-10-15 Thread Stevan Little

Larry,

On Oct 15, 2005, at 11:25 AM, Larry Wall wrote:


On Sat, Oct 15, 2005 at 10:34:34AM -0400, Stevan Little wrote:
: I think what bothers me most about this is that it seems there is no
: way to tell the difference between class methods and instance
: methods. That the distinction is only made when the body of the
: method does something which is is not supposed to do (method called
: with a class invocant attempts to access an instance variable, etc).
:
: This is one of the major problems that I have always had with Perl 5
: OO. That there is a very fuzzy fuzzy line between the
: responsibilities of a class and an instance.

But you haven't actually said why this is a problem.  If you want to
know at compile time that a method must be called with an object that
has been instantiated, it seems to me that it's pretty easy to tell
99% of the time whether the method body has made reference to $?SELF
in some form or other.  And if the compiler can determine that, why
should the user have to specify it?


I think it is a problem because they are two distinct areas of  
responsibility. A class creates and manages instances, while an  
object is the thing which the class creates. The object only manages  
it's own data.


As for whether the compiler can tell the difference, I am not sure  
you are correct here. Take this for instance:


class Foo {
method bar {
$?CLASS.baz();
}
}

What is bar? A class method? or a instance method? Clearly $?CLASS  
is valid inside instance methods, and surely you can call methods on  
$?CLASS within instance methods. There is an ambiguity here.


One possible solution of course is that this method is both, that it  
could basically be this (to use the old A12 syntax):


class Foo {
method bar (Class|Foo $f:) {
$?CLASS.baz();
}
}

I am fine with that personally.

My biggest concern is that we are able to fit the syntax into *a*  
meta-model. As I said before, I don't have a problem scrapping the  
current version and starting on v3.0, I enjoy writing and thinking  
about these things, so you will get no resistance from me. However, I  
want to be sure that I know what it needs to do, then I can determine  
if I even need to re-write it or not.


: I can see the notion of a class which is not yet instantiated,  
this
: makes sense in many contexts. But I don't think that in order to  
have
: this, we need to bring back this element of Perl 5 OO. I think we  
can
: still have all the behaviors you have been describing, and still  
keep

: classes and their instances as distinct entities.

Well sure, they're at least opposite ends of a continuum.  But we
may usefully smudge the distinction in the middle unless you can show
actual damage from this.


I don't think there is actually damage, we just have methods which  
can be called in either context. How to implement this is fairly  
easy, so I am not worried about that. I am just not comfortable with  
*all* methods being in this grey area.



And as you pointed out in your other message,
your notion of class is mostly hidden behind .meta in my scheme of
things anyway.  And generally the compiler will know by inspection
whether the body is referring to the dynamic class through .meta, the
static class through $?CLASS, or the dynamic instance through $?SELF.


Yes, except in the case I show above, but then we can just use the  
solution I show above.


(And yes, it bothers me that $?CLASS is static while $?SELF is  
dynamic.

The latter is an abuse of the $? sigil, which ought to be reserved
for entities known to the compiler.  Maybe we should rename $?SELF
to something that looks more dynamic.  $*SELF is dynamic, but implies
global.  Hmm, if $.foo() is really a self call, maybe we could make a
case for self being $$.  Of course, there's never been any controversy
here about what to call self, oh no... :-)


I don't even want to get into this debate, I am just the meta-monkey,  
nothing more :)


Thanks,

Stevan



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




Lazy Generics side-bar (was Re: Should roles and classes be merged?)

2005-10-14 Thread Stevan Little

Larry,

On Oct 14, 2005, at 1:28 PM, Larry Wall wrote:

Generics are somewhat orthogonal to the mutable/immutable distinction,
except that they're a better fit for roles because someone has to
choose when to instantiate them, and they're easier to understand
with early binding rather than late binding.  So another way to view
the role/class distinction is that roles have eager semantics while
classes have lazy semantics.  I expect it's possible to do lazy
generics, but I would put it in the category of hard things that
should be possible.


I am not 100% sure what you mean by lazy generics vs. eager  
generics. But in the current metamodel prototype I have implemented,  
what I believe to be, lazy generics. It works like so.


Say we have a generic Unit class, which needs a type (::T) for it's  
value:


  class Unit[::T] {
  has ::T $.value;
  }

Now I am assuming that a class body is a closure (which surely it is)  
and that it usually just gets evaluated right away. What if we defer  
that evaluation?


Lets de-sugar the above example a little:

  my $Unit = sub (::T) {
  class Unit[::T] {
  has ::T $.value;
  }
  };

Now we have not yet actually created any Unit classes yet (generic or  
otherwise). Instead we have a closure which given the right set of  
parameters, can create specific instances of the Unit class which are  
parameterized.


Now we create our Unit[Int] class like this:

  my $unit_int = Unit[Int].new();

Which would be just sugar for this:

  my $unit_int = $Unit.(Int).new();

Again, I am not sure if this is what you mean by lazy generics or not.

Stevan




Re: Re(vised): Proposal to make class method non-inheritable

2005-10-14 Thread Stevan Little

Larry,

I have been giving a lot of thought to the way you have been  
describing classes lately. I think I understand where you are going  
with it, but I need to understand some of the details.


On Oct 14, 2005, at 2:15 PM, Larry Wall wrote:

This only reinforces my view that all the meta stuff for Dog must
be via the .meta or the associated package.  There is no Class object.
It's a false dichotomy.  Class is a role that manages partially
instantiated objects, just as Routine (or whatever it is these
days) is a role that manages partially instantiated sub calls.
And they mostly manage by delegation to .meta.


If I understand you correctly then, what I have been calling a class  
object is just really the thing on the other end of .meta.


When I say class object, I mean some kind of object instance which  
contains all the information to describe a class (methods, meta- 
attributes, superclass list, etc). This can just as easily be called  
a metaclass instance too, it makes no difference to me.


As for the idea that Class is a role that manages partially  
instantiated objects, I am not sure i am understanding what you mean  
here. I am assuming this is along the lines of the Class's are a  
special form of undef idea. In that case I can see where maybe the  
Class thing is simply a parameterized role of some kind which has  
the following behaviors:


1) it evaluates to undef in an expression

  my Dog $fido;
  if ($fido) {
  # this won't run, $fido is not yet defined
  }

2) it acts as a proxy if a method is called on it

  my Dog $fido;
  $fido .= new();

If this is true, then maybe Class looks something like this:

role Class[MetaClassType $T] {
# evaluate to false in bool context
method prefix:? () { bool::false }

# probably need to overload some other
# operators here too, but I will leave
# that for now

# the AUTOMETH checks for an calls
# any method you attempt to call on
# this particular class
# ( I am not sure about the details
# of the code here, but you get the
# idea I think )
method AUTOMETH { $T.can($_).([EMAIL PROTECTED]) }
}

Then if this were so, then the following:

  my Dog $fido;

Would be de-sugared into:

  my $fido = Class[Dog].new();

At least this is how I am seeing it currently in my head. Please let  
me know if I am way off the mark here, I am trying to understand how  
this all will work. Ideally it can fit into the current meta-model  
prototype as designed, if not, I have no problem re-writing it again,  
but I just need to wrap my head around how this should work.


Thanks much,

Stevan







Re: What the heck is a submethod (good for)

2005-10-13 Thread Stevan Little


On Oct 13, 2005, at 9:47 AM, Matt Fowles wrote:

On 10/13/05, Brent 'Dax' Royal-Gordon [EMAIL PROTECTED] wrote:

Luke Palmer [EMAIL PROTECTED] wrote:

Okay, I seriously have to see an example of a submethod in use.


Likewise.  As far as I've seen, submethods are a kludge wedged in for
cases where you're actually calling all the way up the inheritence
tree.  Personally, I've always thought a cascade method syntax  
would

be better for that:

post method BUILD($foo, $bar) { ... }
pre method DESTROY() { ... }

Cascade methods would be called (before|after) the indicated  
method in

a superclass was called.


I don't think there is a need to restrict it to the wrapping  
superclasses methods only, there is no reason that you could not also  
have them wrap a local method too if you wanted.


This might actually be a legitimate use for a submethod too.

pre method  foo () { ... } # this is inherited
submethod   foo () { ... } # this is not inherited
post method foo () { ... } # this is inherited

I could see this construct being quite useful in a Template Method  
pattern sort of way.



Their return values would probably be thrown
away.  I think they might actually be a sort of syntactic sugar for
inserting `call` in the method body, but that's an implementation
detail, really...


I have always wondered about the absence of these.  CLOS has them and
they look quite useful.


CLOS has before, after and around method qualifiers actually.  
AFAIK, the return values of these methods are thrown away too, as  
Brent suggests.


One thing to keep in mind is that CLOS has generic functions instead  
of the usual methods-attached-to-a-class scheme. It also has no  
(simple) means of calling superclass methods and capturing the return  
values (at least AFAIK, I am sure someone has hacked the abilities,  
but I don't think it is part of the spec). The method qualifiers were  
added to CLOS to allow for this kind of behavior.


Since Perl 6 does not suffer from this same issue, method qualifiers  
are not *needed* like they are in CLOS. That said, they are a nice  
bit of syntactic sugar (as Brent points out).


Maybe this could be done with traits?

method BUILD ($foo, $bar) is post { ... }
method DESTROY () is pre { ... }

Or possibly with some kind of name-mangling:

method BUILD:post ($foo, $bar) { ... }
method DESTROY:pre () { ... }

Stevan













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(vised): Proposal to make class method non-inheritable

2005-10-13 Thread Stevan Little
Well, I suspected there would not be much support for my initial  
proposal on class methods, but I felt I had to try. Not being the  
type of person who gives up easily, I want to revise the proposal  
(incorporating some of the ideas in the responses).


I propose that class methods are inheritable, but have the following  
behaviors/attributes:


1) Autogenerated Class attribute accessors will be submethods.

This means that this code:

  class Foo {
 our $.bar;
  }

will be functionally identical to this code:

  class Foo {
  our $.bar;
  submethod bar (Class $c:) { $.bar }
  }

This will ensure that class methods which are specifically tied to  
some kind of state within the class will not be inherited. At least  
not by default, if you want that behavior, then you can do this:


  class Foo {
  our $.bar;
  method bar (Class $c:) { $.bar }
  }

2) Class methods be defined more specifically

I think that method (Class $c:) { ... } is kind of ugly, and if we  
use eigenclasses to implement class methods, is not even correct.


Ideally we have some kind of way to represent Larry's Dog but undef  
concept. This could be thought of as being the prototypical instance  
(for those who like prototype based OO), and it would also be the  
invocant for all class methods for Dog.


So anyway, here are a few ideas, in no particular order:

  method bark (::Dog $d:) { ... }
  # not sure if this notation is already taken or not

  method bark ($Dog $d:) { ... }
  # not sure I like this one myself, but to me it helps to re- 
enforce the singleton nature of the class instance


  method bark (Dog) { ... }
  # this would be similar to functional languages where the  
parameter matches a value, not the type of a value.
  # The user would then be forced to use $?CLASS inside (this one is  
probably too much BD)


  classmethod bark { ... }
  # you can't get more specific than this :)

Okay, thats all for now, however, be on the lookout for some other  
mails on the specifics of class method dispatch. If we are going to  
do it, we need to do it right.


Thanks,

Stevan


Custom Metaclass and Inheritance of Class Methods

2005-10-13 Thread Stevan Little

Hey All,

So, given the abundance of positive responses ;) for my class  
methods don't inherit proposal, I have decided to withdraw that  
proposal (see my last response on the thread). Of course, this means  
we now have to work out the details of exactly *how* they get  
inherited in all situations. The trickiest one being in the presence  
of custom metaclasses. So, onto the questions.


(NOTE: if you get bored about half-way through this mail (and you  
probably will), there is a conculsion/wrap-up at the very bottom that  
you can probably safely skip ahead too)


Should custom metaclasses are inherited along normal subclass lines?

This would mean that if Foo uses CustomMeta as it's metaclass, any  
subclass of Foo will do the same. This is something Larry mentioned,  
and something I had been thinking about a lot myself and discussed  
recently with Rob Kinyon. I drew a diagram in my response to Larry  
that looked like this:


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

This shows the structure which would be created. The result is that  
method dispatch would go like this:


Bar.foo
  eBar.get_method(foo)
eFoo.get_method(foo)
  CustomMeta.get_method(foo)
Class.get_method(foo)
  ! No Method Found Error !

I think this makes sense in many ways since CustomMeta can  
theoretically add capabilities to the Foo class, which one would want  
inherited by subclasses of Foo. (NOTE: if CustomMeta adds instance  
methods to Foo, they will get inherited, mostly I am talking about  
class functionality here)


However, I can also see where it would make sense for this *not* to  
behave this way. But if we the opposite approach, the eigenclass/ 
metaclass hierarchy begins to get more complex.


To start with, we would need to create another anon-class (called  
xFoo here) which uses multiple inheritence to inherit from eFoo and  
CustomMeta, then eBar would inherit from eFoo (and through eFoo, to  
Class), this would keep CustomMeta out of Bar's method dispatch path.


  Class
^^...
:   :
CustomMeta  :
^   :
:   :
  xFoo...eFoo...eBar
^   ^
|   |
   FooBar

The resulting method dispatch paths would be:

Bar.foo
  eBar.has_method(foo)
eFoo.has_method(foo)
  Class.has_method(foo)
! Method Not Found Error !

Note the lack of CustomMeta in the dispatch path, where as in the  
above example it was there.


This on it's own is not too bad, however, when we add another  
metaclass, it starts to get busier. Our anon-class xBar must inherit  
from eBar and CustomMeta2 (just like xFoo did). Then eBar must be  
connected to eFoo in order to inherit from it, but not pic up any of  
CustomMeta's methods.


  Class...
^^... :
:   : :
CustomMeta  :CustomMeta2
^   : ^
:   : :
  xFoo...eFoo   xBareBar
^   ^ ^:
|   :.|:
| |
   Foo..Bar

The method dispatch path for this is pretty much the same as above,  
with the addition of CustomMeta2. This example now actually brings up  
another issue.


What should the superclass ordering be within the x* classes?

If eBar comes first, followed by CustomMeta2, then we get the  
following method dispatch path:


Bar.foo
  xBar.has_method(foo) # xBar should never have any of it's own method
eBar.has_method(foo)
  eFoo.has_method(foo)
CustomMeta2.has_method(foo) # this would fall here under C3
  Class.has_method(foo)
! Method Not Found Error !

But if CustomMeta2 comes first, followed by eBar, then we get the  
following method dispatch path:


Bar.foo
  xBar.has_method(foo)
CustomMeta2.has_method(foo)
  eBar.has_method(foo)
eFoo.has_method(foo)
Class.has_method(foo)
  ! Method Not Found Error !

The question really is, which has precedence, the custom metaclass,  
or the local class methods (including class methods inherited along  
normal class lines)?


Now, all these method dispatch paths are using the C3 MRO. And  
personally I find neither of these approaches to be the best. One  
alternate (but kind of whacky) approach would be to not use C3 here,  
but instead use breath-first traversal.


Now, this may seem really odd at first, but given the highly regular  
structure of these class groupings, it might make the most sense.  
Here is what that method dispatch path might look like:


Bar.foo
  xBar.has_method(foo)
eBar.has_method(foo)
  CustomMeta2.has_method(foo)
eFoo.has_method(foo)
  Class.has_method(foo)
! Method Not Found Error !

Notice how the eBar (which hold's Bar's class methods) is first,  
followed by the CustomMeta2 class, the followed by eFoo, then onto  
Class.


This specialized dispatching behavior could (I 

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

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 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

Proposal to make class method non-inheritable

2005-10-11 Thread Stevan Little

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.


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


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

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. Of course the meta syntax there is speculative,  
but surely you can accomplish that behavior somehow. This approach  
actually uses no class methods, only instance methods.


However, as always, there is more than one way to do it, you can  
accomplish the same thing using Roles. Here is how that might look:


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

CountingA = A but Countable;
CountingB = B but Countable;

CountingA.count; # 0
CountingA.new;
CountingA.count; # 1

CountingB.count; # 0
CountingB.new;
CountingB.count; # 1

NOTE: I am assuming that the Countable role will mix-in the class  
method count as well as the class attribute $.count. And that A but  
Countable is really sugar for something like class { does  
Countable; is A }.


== Custom Constructors

Another common example of class method usage is custom constructors.  
This example is moot given the BUILDALL/BUILD system. All class  
specific initialization can easily be done using custom BUILD  
submethods.


This example too is skewed towards a language's particular object  
model as well. In Java/C# the constructor is a special/magical  
thing which is called by the new keyword. In Smalltalk, new is  
actually an instance method of the class Class, and it calls the  
specific object's new instance method to initialize (somewhat like  
the CREATE-BUILDALL/BUILD in Perl 6). In the Perl6-MetaModel  
prototype, new is implemented as an instance method of Class, and  
not a class method of Object (as is sometimes assumed).


== Java-style static methods

Java's static methods are only thought of as being like class methods  
because they have access to other static class members, and they are  
only callable though the class. The Perl 6 equivalent of this  
concept is nothing more than a package sub, and a package variable.  
Since Class isa Package, this type of behavior is easily accomplished.


== Conclusion

Now, I am not proposing we abolish class methods entirely, only that  
we simplify 

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 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









Class Methods, Eigenclasses and $?CLASS

2005-10-10 Thread Stevan Little

Evening all,

So I am in the process of adding class-methods into the meta-model  
using eigenclasses. Eigenclasses are a ruby thing (and also a CLOS  
thing IIRC), in which an anon-class is inserted between an instance  
and it's class, essentially replacing the instance's class. The anon- 
class then adds the original class to it's superclass list. This is  
best shown visually I think:


 ::Class
^
:  -- eFoo is a subclass of Class
:
 ::eFoo   # eFoo is also an instance of Class
|
|  -- eFoo is the class of Foo
V
  ::Foo

The dispatching of instance methods is still the same, and everything  
just works. Well... almost everything.


There is a slight issue/inconsitency with how $?CLASS works.

class Foo {
method bar (Class $c:)  { $?CLASS }
method baz (Foo $self:) { $?CLASS }
}

Within the bar class-method, the natural inclination is to think  
that $?CLASS will refer to ::Foo. However, in order to be consistent  
it actually refers to the eigenclass between ::Foo and ::Class, lets  
call it ::eFoo. This is because methods are associated with the class  
which contains them. In the baz instance-method, $?CLASS does refer  
to ::Foo, since ::Foo is the class which contains baz.


It seems to me that this inconsistency could be very problematic,  
especially since eigenclasses should really be an invisible  
implementation detail.


I am not 100% sure of what is the correct approach here, so I thought  
I would ask the group. Any thoughts guys/gals?


Thanks,

Stevan




Re: Class Methods, Eigenclasses and $?CLASS

2005-10-10 Thread Stevan Little

Luke,

On Oct 10, 2005, at 7:47 PM, Luke Palmer wrote:

How do you explain this:

class Foo {
method bar (Class $class:) { class method }
}
say Foo.bar;# class method
my $foo = Foo.new;
say $foo.bar;   # class method

Assuming that that is valid Perl.


It is valid Perl 5, however (IMHO) it is *not* valid Perl 6.

To start with, the type of the invocant is Class, which $foo is not  
derived from (it is an instance of something which itself is an  
instance of Class).


I think that

  $foo.class.bar()

should work. And changing the method defintion to be

  method bar (Class|Foo $class:) { ... }

should work, but the code as you wrote it should not. Which means  
that when we deal with Perl 5 classes within Perl 6, we should likely  
give them an implied signature of (Class|Foo $self:) or some other  
weirdness (I haven't thought that far down the line yet).


Class methods are strange creatures, in Perl 5 they were nothing  
different than instance methods. In Java (static methods), they are  
really just odd functions which need to be qualified by a class name.  
Python doesn't even really have them (you have to jump through odd  
hoops to make the method callable). Ruby uses Eigenclasses, and  
CLOS uses something akin to eigenclasses. I am not sure how Smalltalk  
handles things, but my guess is that class methods on Foo are  
instance methods of classFoo, or some such.


They are ugly beasties no matter what, but eigenclasses (so far) seem  
to be the prettiest of the uglies.


Stevan




Re: Object Model Pictures

2005-09-21 Thread Stevan Little

Nathan,

On Sep 21, 2005, at 9:02 AM, Nathan Gray wrote:

On Tue, Sep 20, 2005 at 08:16:23PM -0400, Stevan Little wrote:


http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel2.0/docs/
p6_role_model.jpg

I am planning on making Roles self-bootstrapping, so the class(Role)
will actually be the first Role in the system. From there, Class will
do Role, and Role will do Role. This also means that all the
instances of Class will also do Role, which means that classes
automatically can also be used as Roles.



Thanks for the pictures, Stevan.

So every time a class does a new role, a new instance of the class is
created as the role.


Nope. The Role interface is (for the most part) a subset of the Class  
interface, well at least the important bits are. So I manually  
bootstrap the role(Role) into the class(Class), this then means that  
Class.does(Role). THis means that all instances of Class (all the  
user defined classes) themselves also do Role. This means that all  
Classes then become interchangeable with Roles. No new class or role  
instances need to be created, it is all inherited behavior from the  
class(Class).



If a class does three roles, there will be three role instances of
the class, as well as the class' own instance of itself, and a user
instance.


No, Roles are disposed of once class composition is complete. Part of  
the class composition process will be to consume any Roles which the  
class does. THe consumption process takes all the methods and  
attributes from the Role and actually adds them into the class. After  
that, the role can essentially be discarded (unless another class  
uses that same role).




When a method is called on the user instance, it asks the class  
instance
if it can do the method, and the class instance looks at the  
methods in

the class, and then at the methods in each role, and dispatches to the
appropriate method definition.


The dispatch is always in the class since role methods are consumed  
into the class.


A role can be done by several classes at once, because a new  
instance

is created for each class, specific to the class.

Methods defined in a class are not clobbered by methods defined in a
role.  Rather, methods in a role are only catalogued by the class
instance if it does not already have a method definition for that  
name.

The order that a class does roles is significant, because if two roles
define the same method, only the first one is catalogued by the class
instance.


Class methods are used first, if the class method is not there, then  
the Role method is used. If there is a conflict with Role methods,  
neither Role method is used. By making all conflicts behave this way,  
we make Role order not-significant. Also If two Role methods  
conflict, the class consuming the roles must implement that method,  
otherwise it is a fatal error.


Stevan




-kolibrie






Re: Object Model Pictures

2005-09-20 Thread Stevan Little


On Sep 12, 2005, at 3:56 PM, Nathan Gray wrote:

Yep, someone needs to make a diagram about Roles, too.



Here yah go.

http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel2.0/docs/ 
p6_role_model.jpg


I am planning on making Roles self-bootstrapping, so the class(Role)  
will actually be the first Role in the system. From there, Class will  
do Role, and Role will do Role. This also means that all the  
instances of Class will also do Role, which means that classes  
automatically can also be used as Roles.


Here is a mini-meta-model variation which implements this on a very  
basic level:


http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel2.0/docs/ 
MiniMetaModel_w_Role.pl


There is also an ASCII diagram here:

http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel2.0/docs/ 
misc_drawings.txt


I was planning on getting Role into the metamodel by the end of this  
week, but it seems $work might get in the way.


Stevan



Object Model Pictures

2005-09-12 Thread Stevan Little

Hello again.

In my never ending quest to implement the Perl 6 object model, I have  
started drawing pictures. Here is the latest version:


http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel2.0/docs/ 
p6_object_model.jpg


(and for OmniGraffle users: http://svn.openfoundry.org/pugs/perl5/ 
Perl6-MetaModel2.0/docs/p6_object_model.graffle)


I would appreciate any comments/questions/suggestions anyone has to  
offer.


A few things to note:

- Roles are not yet included in this, I am of the opinion that the  
core MetaModel should be role-less, and roles will be laid on top of  
the core metamodel post-bootstrapping. This makes the most sense  
currently, however, this may change down the road, either way I think  
it is an implementation detail as long as it looks the same when  
everything is loaded.


- the word meta is used to describe the three-circle items.  
Please do not read to much into this terminology, meta simply means  
you should not touch this unless you *really* know what you are  
doing. Suggestions on better names are welcome.


- the reason Foo and $foo are smaller is because they are user  
created items.


Okay, thats all my caveats, fire away please.

Stevan


Re: Regarding Roles and $?ROLE

2005-09-11 Thread Stevan Little

 From: Luke Palmer [EMAIL PROTECTED]
On 9/11/05, Stevan Little [EMAIL PROTECTED] wrote:
 Hello all.
 
 I have some questions about how Roles will behave in certain
 instances, and when/where/what $?ROLE should be bound too.
 
 1) Given this example, where 'bar' is a method stub (no implementation)
 
 role Foo {
  method bar { ... }
 }
 
 Should the eventually implemented method still have a binding for $?
 ROLE?

The way you're referring to $?ROLE here sounds kind of akin to asking
*the* type (not class) of a particular object.  That is, you're asking
the compiler for the answer to a question that doesn't make any sense.

I do not see $?ROLE as refering to the type of the object, I would think we 
should use 
does() for that. I see $?ROLE as being like $?SELF and $?CLASS in that it is 
just a 
pseudo-lexical which is only bound in certain situtions (inside a method 
defintion, 
inside a class definition, etc). It seems to me that $?ROLE should be bound 
within a Role 
defintion as well, and this of course means it is defined within role methods 
as well. 
However, method stubs are a grey area. The stub is defined within the Role, and 
so a 
part of the Role, but the eventual method defintion is done by the consuming 
class, 
which is not part of the Role. 

Honestly, my vote is for no. I think $?ROLE only really makes sense within the 
context of 
the Role, and I am not really sure I see much use for it outside of this anyway.

Stevan




Regarding Roles and $?ROLE

2005-09-10 Thread Stevan Little

Hello all.

I have some questions about how Roles will behave in certain  
instances, and when/where/what $?ROLE should be bound too.


1) Given this example, where 'bar' is a method stub (no implementation)

role Foo {
method bar { ... }
}

Should the eventually implemented method still have a binding for $? 
ROLE?


2) When a Role itself has subroles, which are composed together and  
consumed by the parent Role, how is $?ROLE bound? is it the top-most  
Role which it is bound too? or is it bound to the Role it originally  
came from? Here is an example:


role Foo {
method foo { $?ROLE }
}

role Bar {
method bar { $?ROLE }
}

role FooBar does Foo does Bar {}

Given this code, does FooBar::foo return FooBar? or Foo? And what  
about FooBar::bar?


This also brings up another question.

3) Using the Roles above, what will this code do?

class MyClass does FooBar {
method foo {
$?SELF.FooBar::foo();
}
}

Since Roles are flattened, I would think it is reasonable to assume  
that FooBar::foo exists. However, it does not exists in the concrete  
in-the-namespace-stash sense. Should fully qualified access to Role  
methods be mediated by some kind of proxy? Should it actually query a  
composite Role of some kind?


The easy way I think, is to say the above code will fail since  
FooBar::foo does not exist. However consider for a moment how Role  
composition works, and how flattening sort of equalizes all the  
methods and makes ordering unimportant. These qualities are what give  
Roles such great compositional power, and reduce the complexities/ 
issues usually associated with mix-ins and multiple inheritance. If  
you force the user to see the entire Role hierarchy, and not just the  
topmost Role, are you loosing some of that compositional power?


And lastly ...

4) If a Role has a method stub, you are in effect creating a contract  
with any class which consumes that Role. The class must implement  
that method. However, what happens if the class consumes another Role  
which implements that method. Do they still conflict? or does the  
second Role's version fufill the first Role's contract?


Here is a quick code example:

role Foo {
method foo { ... }
}

role Bar {
method foo { Hello World.say }
}

class FooBar does Foo does Bar {}

Does this work? Does Bar fufill Foo's implied contract? Or is an  
exception thrown here?


Thanks,

Stevan



Re: Packages, Modules and Classes

2005-09-08 Thread Stevan Little

Larry,

On Sep 8, 2005, at 2:30 PM, Larry Wall wrote:

On Wed, Sep 07, 2005 at 03:00:29PM -0400, Stevan Little wrote:
: Also, is there anyway to iterate over the keys in the namespace? The
: old way would be to do something like keys(%Foo::). Is something like
: this possible with the new way?

Sure, it's still just a hash, basically, so Foo.keys() works fine.
All we've changed is that we've removed a special syntactic case by
allowing a type/package object to pretend to be a hash when used that 
way,

just as we allow it to pretend to be an undef when used as an instance.
Tagmemics strikes again...


But what if I want to do this?

class Foo {
my %:stuff;
method keys (Class $c:) {
%:stuff.keys();
}
}

How can I get at my namespace now? How would I disambiguiate that call? 
Doing something like Foo.Package::keys() seems to me to be exposing too 
much of the meta-level (the Package class).


I can see lots of  potential conflict between class methods and methods 
to access the contents of a namespace (methods defined in the Hash role 
I assume). This means that Foo is getting even more and more magical. 
It's now a type annotation, a special undef value, the invocant in 
class methods and the gatekeeper of the namespace.


Stevan



Re: Packages, Modules and Classes

2005-09-08 Thread Stevan Little

Larry,

On Sep 8, 2005, at 5:07 PM, Larry Wall wrote:

On Thu, Sep 08, 2005 at 04:52:52PM -0400, Stevan Little wrote:
: But what if I want to do this?
:
: class Foo {
:   my %:stuff;
:   method keys (Class $c:) {
:   %:stuff.keys();
:   }
: }
:
: How can I get at my namespace now? How would I disambiguiate that 
call?
: Doing something like Foo.Package::keys() seems to me to be exposing 
too

: much of the meta-level (the Package class).
:
: I can see lots of  potential conflict between class methods and 
methods
: to access the contents of a namespace (methods defined in the Hash 
role

: I assume). This means that Foo is getting even more and more magical.
: It's now a type annotation, a special undef value, the invocant in
: class methods and the gatekeeper of the namespace.

Well, like I said, we can require the extra :: in cases of ambiguity.  
It's

really only the misplaced sigil I'm trying to get rid of.


So it would be Foo::.keys() then?

Would this be possible?

my $pkg = Foo::;
# or maybe this ...
my $pkg = Foo::;

Would $pkg be an instance of the Package class? I would assume given 
this code:


package Foo {
...
package Foo::Bar {
...
}
}

I can do this:

my $pkg = Foo::{'::Bar'}

And get back some kind of Package reference of some kind.

Do we even have first class packages?

h

Stevan




Re: Packages, Modules and Classes

2005-09-07 Thread Stevan Little

Larry,

On Sep 7, 2005, at 11:46 AM, Larry Wall wrote:

: I base this off the AUTO* hooks described in
: S10. I assume too that the METH slot is only valid for Classes, and 
not

: appropriate for Packages and Modules.

All those entries are based on the notion of intuiting from the first
character of the variable name within the symbol table, not from having
separate typeglobbish slots within each symbol.


How do I differentiate a method from a sub? Wouldn't they both have the 
 sigil?



:   class Foo;
:   has $.baz;
:   method bar { ... }
:
: Can I get to $.baz? If I can, what will I get?

All sigils and twigils are part of the key to the symbol table, so it's
now just

Foo$.baz


What would Foo$.baz return though (assuming Foo is a class)? It 
cannot return a value since it is an instance specific value. Should it 
return some kind of meta-object? Or possibly the default value 
specified (if one is specified)? Can this value be written too? If so, 
how does that affect things?


Also would/should this work:

$iFoo$.baz

As a means of breaking the opaque instance data structure. (I for one, 
vote no on that).


- Stevan



Re: Packages, Modules and Classes

2005-09-07 Thread Stevan Little

Larry,

On Sep 7, 2005, at 12:45 PM, Larry Wall wrote:
: All sigils and twigils are part of the key to the symbol table, so 
it's

: now just
: 
: Foo$.baz
:
: What would Foo$.baz return though (assuming Foo is a class)? It
: cannot return a value since it is an instance specific value.

Foo@baz is not a value either, but a container.  I would say that
Foo$.baz returns a generic container that happens not to work
without an extra instance argument to say which chunk of data to map
the container metainfo onto.

: Should it return some kind of meta-object?

Yes.


If methods and subs are in the same namespace, and both have the  
sigil, what about instance attributes and class attributes? Is this 
legal?


class Foo {
my $.bar;
has $.bar;
}

Part of me thinks that it should be since my $.bar is an attribute of 
the Foo class, and has $.bar is an attribute of instances of Foo.


Also, is there anyway to iterate over the keys in the namespace? The 
old way would be to do something like keys(%Foo::). Is something like 
this possible with the new way?


Thanks,

Stevan



Packages, Modules and Classes

2005-09-06 Thread Stevan Little

Hey all,

I recently added Package and Module into the MetaModel (2.0) so that

   Package is an Object
   Module is a Package
   Class is a Module

as mentioned here 
http://article.gmane.org/gmane.comp.lang.perl.perl6.language/4599. 
Currently Packages have names and Modules add version and authority 
information, but I have nothing yet in place to represent package 
symbol tables. Which brings me to my questions.


I assume that each symbol table entry has the following slots; SCALAR, 
ARRAY, HASH, SUB, METH. I base this off the AUTO* hooks described in 
S10. I assume too that the METH slot is only valid for Classes, and not 
appropriate for Packages and Modules.


This would mean that given this code:

  package Foo;
  our $baz;
  sub bar { ... }

%Foo::{'bar'}{SUB} is a ref to the bar sub, and %Foo::{'baz'}{SCALAR} 
is a ref to the scalar $baz. The same, I would assume, would apply for 
Modules, so that:


  module Foo;
  our $baz;
  sub bar { ... }

is pretty much interchangable with the first example. But I think it's 
a little trickier when we get to Classes. Given this code:


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

I would expect it to behave just as it does for a Package or Module. 
But when we start to introduce methods and attributes, I am unsure of 
how things will work.


  class Foo;
  has $.baz;
  method bar { ... }

Can I get to $.baz? If I can, what will I get?

I expect that %Foo::{'bar'}{METH} will give me a method ref, but what 
happens when I try to store something in it? Does that perform some 
kind of meta-model actions (Foo.meta.change_method(...) or somesuch)? 
What if I delete the symbol table entry, what happens then (more 
meta-trickery)?


Thanks,

Stevan







scopes of $?SELF and $?CLASS

2005-08-17 Thread Stevan Little

Hello all,

I tried to search for this answer in AES12, but I did not see anything, 
and a perl6.lang search just brought up the whole $_.method vs. 
./method debate (which was too much to shlog through).


So, onto my question, I am wondering what are the valid scopes for 
$?SELF and $?CLASS.


Are these (magical) globals who only have bound values in certain 
contexts? If that is so, what value do they have outside of a valid 
context? undef? or is attempting to accessing the value a runtime 
exception?


Or ...

Is it a syntax error to access them outside of a valid scope, and 
therefore caught at compile time? In this case, then it seems to me 
that they are not behaving as global variables so much as they are 
behaving like language keywords.


Now as for the valid contexts.

The obvious one is that they are both valid within a method. I asumme 
that $?SELF is bound to the invocant, and $?CLASS is bound to the class 
the method was defined within. It seems to me that this also mean that 
in a class method, that $?SELF == $?CLASS?


Also (IIRC) we discussed $?CLASS being valid inside a class Foo { ... } 
block at the hackathon. Would mean that something like this should be 
possible.


  class FooLoggerProxy is Foo {
  has Logger $.logger;
  for ($?CLASS.meta.superclasses()) - $super {
  for ($super.meta.getmethods()) - $method {
 $?CLASS.meta.add_method($method.label = method {
  $?SELF.logger.log($method.label ~  has been called);
  return $method.do([EMAIL PROTECTED])
 });
}
  }
  }

I am not sure if there are any other valid contexts other than inside a 
method or a class composition block. At least none that I can think of.


Thanks,

Stevan



Re: scopes of $?SELF and $?CLASS

2005-08-17 Thread Stevan Little


On Aug 17, 2005, at 2:28 PM, Ingo Blechschmidt wrote:

Hi,

Stevan Little wrote:

So, onto my question, I am wondering what are the valid scopes for
$?SELF and $?CLASS.

Are these (magical) globals who only have bound values in certain
contexts? If that is so, what value do they have outside of a valid
context? undef? or is attempting to accessing the value a runtime
exception?


hm, I've thought of these as follows:

class Foo {...}# is really
class Foo {
my $?CLASS := Foo;
...;
}

method bar($self:) {...}   # is really
method bar($self:) {
my $?SELF := $self;
...;
}


Yes, this is how I saw it too.


The obvious one is that they are both valid within a method. I asumme
that $?SELF is bound to the invocant, and $?CLASS is bound to the
class the method was defined within. It seems to me that this also
mean that in a class method, that $?SELF == $?CLASS?


I think so, too.


Also (IIRC) we discussed $?CLASS being valid inside a class Foo { ...
} block at the hackathon. Would mean that something like this should
be possible.

   class FooLoggerProxy is Foo {
   has Logger $.logger;
   for ($?CLASS.meta.superclasses()) - $super {
   for ($super.meta.getmethods()) - $method {
  $?CLASS.meta.add_method($method.label = method {
   $?SELF.logger.log($method.label ~  has been
   called); return $method.do([EMAIL PROTECTED])
  });
}
   }
   }


I'd opt for yes.


I am not sure if there are any other valid contexts other than inside
a method or a class composition block. At least none that I can think
of.


role, submethod?


I think in a Role, $?SELF would still be the invocant in a method, and 
$?CLASS would (eventually) bind to the class the role was composed 
into.


As for submethods, I see them like this:

submethod foo () { ... }

is really ..

submethod foo () {
next METHOD unless $?SELF ~~ $?CLASS;
}

At least that is how larry explained to me about a month ago.

Stevan





--Ingo

--
Linux, the choice of a GNU | Mathematicians practice absolute freedom.
generation on a dual AMD   | -- Henry Adams
Athlon!|






Re: scopes of $?SELF and $?CLASS

2005-08-17 Thread Stevan Little

Larry,

On Aug 17, 2005, at 2:53 PM, Larry Wall wrote:

: As for submethods, I see them like this:
:
: submethod foo () { ... }
:
: is really ..
:
: submethod foo () {
:   next METHOD unless $?SELF ~~ $?CLASS;
: }
:
: At least that is how larry explained to me about a month ago.

Can't use ~~ for that, since ~~ implies does, which is not an
exact class match.  Probably need

next METHOD unless $?SELF.class =:= $?CLASS;

or some such.


In the 2.0 version of the metamodel I compare the class object's .id to 
the instance's class object's .id. Which is (I assume) how =:= would do 
it under the hood.



 Except that BUILDALL/DESTROYALL have to be able to
invoke submethods on partial objects whose actual class is not the
same as the submethod, so there needs to be some way of forcing
$?SELF to consider itself in $?CLASS temporarily for infrastructural
purposes.  Maybe it's as easy as temp $obj.class := $tmpclass
in the BUILDALL/DESTROYALL dispatcher.  I dunno.


I am not sure if changing classes makes sense here so much as just 
providing a means for submethod calls to be forced. Currently the 
metamodels do this by allowing a special parameter in the first 
argument which is a flag to let the submethod wrapper know if can skip 
the next METHOD branch. It is a bit of a kludge, but it seems to 
work.


The other option I considered was to make BUILDALL and DESTORYALL 
special somehow. But I am not sure if this makes any more sense than 
the kludge described above.


Stevan




Larry





Re: Perl 6 Meta Object Protocols and $object.meta.isa(?)

2005-08-09 Thread Stevan Little

Guten Tag Herr Sandlaß,

On Aug 9, 2005, at 4:48 AM, TSa (Thomas Sandlaß) wrote:

HaloO,

Stevan Little wrote:
Here is a 10,000 ft view of the metamodel prototype I sketched  out 
the other day  
(http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel/docs/ 
10_000_ft_view.pod). It should shed a little light on this 
discussion.


There you have

i(Foo) - instance of Foo
Foo- the user-level Foo class
class(Foo) - the instance of Perl6::Class named Foo
meta(Foo)  - the instance of Perl6::MetaClass which describes Foo

The thing which is clear to everybody---even including stupid me---is 
that
there is a 1:n relation between Foo and i(Foo). But then comes a three 
part
referential chain Foo - class(Foo) -- meta(Foo) that to me is 
conceptually
*one* thing. The levels of indirection are implementation details, 
right?


Yes, and no. Please see the second email I sent to Mark. It explains 
the role I see for ::Class instances, and why they are not just 
::MetaClass instances.


Also please keep in mind that I am an implementation monkey, and so 
most anything I am documenting is likely to be the implementation and 
not the theory. So assuming things are implementation details is 
usually the right assumption :)


The next level where a 1:n relation exists is below meta(Foo) to pure 
meta.


Not entirely, class models are not as neat and tidy as type models, you 
have many more cycles. To start with, meta(MetaClass) is an instance of 
MetaClass (this is the traditional object model cycle), it is also a 
subclass of Object, and then meta(Object) is also an instance of 
MetaClass.


--- is subclass of
... is instance of

   meta(MetaClass)
   : ^
   : :
   V :
  MetaClass -+
  ^  |
  :  |
  :  |
 meta(Object)|
  ^  |
  :  |
  :  |
   Object --+

However since this is cyclical, you end up with the Which came first, 
the chicken of the egg? issue. So in the implementation I have 
created, the X instance of X part is accomplished through a has-a 
relationship with the ::Class intsances, so that a ::Foo instance has-a 
::Class instance which has-a ::MetaClass instance. Throw in some 
AUTOLOAD trickery and you have a prototype.


Am I missing something? Conceptually I see *one* MetaClass which 
manages

its class instances which in turn manage their object instances.


No, there is no *one* MetaClass to manage them all. AFAIK this was 
something they tried with Smalltalk 72 and found it was problematic, so 
they went to the every Class instance has a MetaClass instance and 
things worked out much better. However since I was not alive (and 
certainly not programming) in '72 I cannot give you any more details 
that that.


OK, it's slightly more complicated because classes can have class 
instances


That does not make it any more complicated. If you think of ::Class 
instances as being like regular instances, only just acting upon the 
class level methods and attributes, you can see that things are pretty 
consistent.



and
there is multiple inheritance that adds edges into the tree which 
transform

it into a DAG.


Nothing in an object model is ever a DAG, there are always cycles. And 
MI does not complicate things either, a MetaClass just holds a list of 
superclasses, thats it, nothing more.



 And I see also classless objects.


Yes, but those are not going to be handled in the meta-model, because 
the meta-model is all about classes. You can however, build a classless 
system on top of the metamodel, using classes of course.


Ahhh, the circularity of it all :)

Once you get used it it, it is really a beautiful thing.

- Stevan


--
$TSa.greeting := HaloO; # mind the echo!





Re: Perl 6 Meta Object Protocols and $object.meta.isa(?)

2005-08-09 Thread Stevan Little

Stuart,

On Aug 9, 2005, at 9:25 AM, Stuart Cook wrote:

Stevan,

Up until today, I thought I had a good idea of how your metamodel
works, but now I'm confused.  My main sticking point is that a class
Foo seems to have three different aspects:

Foo
class(Foo)
meta(Foo)

For each of these, could you please try to explain:
1) Roughly what its responsibility is (and how it relates to the 
others)

2) Whether it is actually an object
3) If so, what its class is


I will simply add to your explanations below (the are mostly correct). 
Keep in mind, as I said to TSa, I am coming from a implementation point 
of view, and so much of what I descibe will be about the 
implementation.



I realise that some of these details are probably spread around
Synopses, source code, and the inside of your own head, but it would
really help to have a concise, clear definition of each.


Yes, sorry. This is why I am trying to document it now.



So far, this is what I have picked up; some/most of it is probably 
wrong:


~ Foo ~
Is a type that variables etc. can be declared to have


That is one way to look at it I suppose. The reality is that there will 
be no actual 'Foo', at least not in the metamodel. 'Foo' is a magical 
interpreter concept, which is really just an 
alias/pointer/level-of-indirection/whatever for class(Foo).


This is all, of course, implementation details.


Is not an object


Nope... its magic :)


  = I'm really not sure about this...


ahh, but you were correct. Trust your instincts Stuart  the force is 
strong with this one I think 




~ class(Foo) ~
Used as the invocant of class methods


Yes. It is also the connection between the concrete instance and 
concrete metaclass instance.



  = Any other purpose?


In autrijus's version of the model it also stores the index of the 
attribute in the instance storage array. But other than that, no it has 
no other purpose in my eyes.



Is an object; instance of the 'Class' class


Perl6::Class in the p5 metamodel. I also find adding either the Perl6:: 
or just :: at the front of names like 'Class' are helpful.



  = How do we get properly-typed access to members that class(Foo) has
 that aren't declared in 'Class'?


class(Foo) instance methods will be for 'Foo', and the class methods 
will be for ::Class.


The current metamodel hacks this in a kind of ugly way, but that is how 
I am seeing it.




~ meta(Foo) ~
Members contain info /about/ Foo, rather than /of/ Foo


Yes, the metaclass basically stores the name, version, authority, 
superclass list, private method table, public method table and 
attribute list. All the things which make up a class (yes, I am 
fluffing the details here a bit, but you get the idea).



  = This is to avoid name-clashes with 'name', 'authority' etc.


That is not really the reason, but yes it does mean that there are no 
restrictions placed on class methods for 'Foo'.



Is an object; instance of the 'MetaClass' class


Yes sir. That is correct.

All in all Stuart, you were pretty much right on.

Stevan




Thanks,
Stuart





Re: Perl 6 Meta Object Protocols and $object.meta.isa(?)

2005-08-09 Thread Stevan Little


On Aug 9, 2005, at 12:36 PM, TSa wrote:

HaloO Stevan,

you wrote:

Guten Tag Herr Sandlaß,


you know that a formal German greeting in a collequial
environment can be interpreted as unfriendly? I don't
do that but just wanted to state the fact.


My apologies, no unfriendliness intended :)

The next level where a 1:n relation exists is below meta(Foo) to 
pure meta.
Not entirely, class models are not as neat and tidy as type models, 
you have many more cycles. To start with, meta(MetaClass) is an 
instance of MetaClass (this is the traditional object model cycle), 
it is also a subclass of Object, and then meta(Object) is also an 
instance of MetaClass.

--- is subclass of
... is instance of


I'm not a good meta modeler---actually I'm none at all.


They are icky beasts and can cause ulcers, I suggest avoiding them at 
all costs :)



But I get as much as that you built a referential fabric
between five data structures. Some of them are used
for walking 'up the instanciation chains' and the other
for hangling along the 'subclassing links'. But what exactly
is the difference between these two? What are they used for?


Actually I think it is 4 data structures, if I understand your question 
correctly. 1) the instance, 2) the magic 'Foo' class, 3) the class(Foo) 
(is instance of Perl6::Class) and 4) meta(Foo) (an instance of 
Perl6::MetaClass).


They are mostly used for walking 'up the instanciation chains' for 
things like;


- to collect all relevant attributes
- method dispatch
- ordered destruction
- etc.

I do not hangle along the 'subclass links' because I actually don't 
store subclass links. I considered adding them, but to be honest, I 
have yet to encounter a real use for them short of introspection.


However since this is cyclical, you end up with the Which came 
first, the chicken of the egg? issue. So in the implementation I 
have created, the X instance of X part is accomplished through a 
has-a relationship with the ::Class intsances, so that a ::Foo 
instance has-a ::Class instance which has-a ::MetaClass instance. 
Throw in some AUTOLOAD trickery and you have a prototype.


So, you basically create the gang of five above from the outside
and link them together. I've no problem with that.


Yes, basically, this is the bootstrapping code. It is the ugly 
underbelly of the metamodel.


Am I missing something? Conceptually I see *one* MetaClass which 
manages

its class instances which in turn manage their object instances.
No, there is no *one* MetaClass to manage them all. AFAIK this was 
something they tried with Smalltalk 72 and found it was problematic, 
so they went to the every Class instance has a MetaClass instance 
and things worked out much better. However since I was not alive (and 
certainly not programming) in '72 I cannot give you any more details 
that that.


But Smalltalk is a typeless language that dispatches along the lines
of the (meta)class/(meta)object links. I propose to call this kind
of thing slot dispatch and reserve single and multi method dispatch for
the type based approach. Don't get me wrong, I consider them all as
equally usefull tools that belong into a state of the art programming
language. The only question is which gets the nicest syntax. And I
guess the meta model by its nature of beeing 'behind the illusion
of simplicity' has to take the burden of beeing somewhat uglier or
more verbose or some such.


Yes, the metamodel will surely have many ugly and verbose corners. This 
is expected for bootstrapping a reflective metamodel of this kind.


As for your dispatch-ing point. I am not sure I understand what you are 
saying, it seems almost as if you are arguing for a generic-function 
approach like CLOS/Dylan rather than a methods-stored-in-class approach 
like most mainstream OO. Is that correct, or am I reading in too far?


IMO, generic functions are really really really really nice things. 
However, they are hard to understand for most programmers, so they are 
not really viable (unless you hide them under a nice UI).


OK, it's slightly more complicated because classes can have class 
instances
That does not make it any more complicated. If you think of ::Class 
instances as being like regular instances, only just acting upon the 
class level methods and attributes, you can see that things are 
pretty consistent.


Hmm, again: what distinguishes classes from objects and meta classes 
from

meta objects?


Nothing, everything is an Object (for the most part, that is). The 
distinction between meta-level and user-level (or as they call it in 
The Art of MOP, backstage and on-stage) is really an artificial barrier 
which the interpreter sets up. The purpose of the meta-object protocol 
is to document how much of the backstage is actually visible from 
on-stage.



I mean other then beeing different nodes in a referential
fabric? BTW, is there a good name for it? I guess Matrix is also 
over-used.


My view is that Perl6 should have
  a name tree,
  a 

Re: Perl 6 Meta Object Protocols and $object.meta.isa(?)

2005-08-09 Thread Stevan Little


On Aug 9, 2005, at 10:52 AM, TSa wrote:

~ Foo ~
Is a type that variables etc. can be declared to have
Is not an object
  = I'm really not sure about this...


Bare Foo is a namespace lookup.


Yes, TSa is right. Everything below this is Type-stuff and I will leave 
that to him (up until the Meta part that is).



The associated type
is something like 'direct instance of Foo'. It is
checked with the .does method. This type is then
used as type parameter to constrain one of the Fantastic
Four ($@%):

   my Foo $foo; # $foo now of type 'Undef of Foo'

   foo = Foo.new; # type correct because Foo.new.does(Foo)



~ class(Foo) ~
Used as the invocant of class methods
  = Any other purpose?
Is an object; instance of the 'Class' class


From the type system point of view class(Foo) is a Class type.
But that is what bare Foo means anyway if the innermost entry
in the namespace was generated from the class special form.


  = How do we get properly-typed access to members that class(Foo) 
has

 that aren't declared in 'Class'?


Sorry, I don't understand that. What do you want to access?
Private class data? Or even lower level implementation details?
Everything else should be accessible through namespace syntax:

  Foo::action(); # action call through Code ref
  $Foo::attr; # data slot access
  @Foo::attr[42]  # array slot

  given Foo  # binds block owner $/ to Foo, $_ from outside
  {
::action();  # action() etc. work as well
$::attr;
@::attr[42];

# or with my idea of slot accessor expressions
# bound through $/ := Foo

.action();
$.attr;
@.attr[42];

# or with method dispatch that does not necessarily
# end up calling a slot in Foo

my method action # hide OUTER::action
{
  say no Foo method but invocant.does(Foo) is $/.does(Foo);
  # what would next METHOD call here?
}
# Note that 'my multi method action' would temporarily install
# action in an existing outer multi or create a new local one and
# and install an outer non-multi in it or some such.
# I'm not the dispatch Guru ;)

.action(); # prints no Foo method but invocant.does(Foo) is true
.attr; # MMD could select Foo::Item::attr accessor
.attr[42]; # MMD could select postfix:[ ](Foo::Array::attr, 42)
  }



~ meta(Foo) ~
Members contain info /about/ Foo, rather than /of/ Foo
  = This is to avoid name-clashes with 'name', 'authority' etc.
Is an object; instance of the 'MetaClass' class


If avoiding name clashes is all, a simple Foo::META pseudo
namespace and %META hash would do. Why a MetaClass and instances of it?


Avoiding name clashes is one point, and I tried the Foo::META thing at 
one point. Actually the current meta-model grew out of that early 
prototype, but soon it outgrew that. IIRC it lead to a lot of code 
duplication, which likely was an implementation detail.



I hope that .isa, .does and .meta are normal Method subtypes and *not*
slots on some implementation objects/structures.


I am not sure I understand this. Can you elaborate?

Stevan


--
$TSa.greeting := HaloO; # mind the echo!





$object.meta.isa(?) redux

2005-08-09 Thread Stevan Little

Howdy,

I wanted to make sure this question had a chance to get addressed, so I 
am seperating it from the other thread which has digressed into the 
depths of the metamodel (much to my delight too).


So..., as described in the other thread, the following statements are 
true about the metamodel.


1) MetaClass is a subclass of Object
2) MetaClass is an instance of MetaClass

So the following code should be true (given a random instance $obj).

  $obj.meta.isa(MetaClass);
  $obj.meta.isa(Object);

Because after all, the object returned from $obj.meta should be a 
MetaClass instance right?


However, Syn/Apoc 12 shows that the following is true if $foo is an 
instance of the Foo class.


  $foo.meta.isa(Foo)

And that $foo.isa(Foo) actually is just an alias for $foo.meta.isa(Foo).

So I am sure you can see my problem here.

The p5 prototype currently handles it as such:

  $foo-isa(Foo) # returns true if $foo is an instance of Foo
  $foo-meta-isa(MetaClass) # returns true since $foo-meta returns a 
MetaClass instance

  $foo-meta-is_a(Foo) # returns true, note the added '_'

Personally I am not a fan of the 'is_a' name, I just did it one day, 
and it sort of stuck. But I do think we need to find a way to 
differentiate between the two questions:


- What class are you an instance of?
- What class are you describing?

The first question can be asked of anything which inherits from Object. 
The second question is really only relevant to MetaClass instances.


Thoughts, Comments, Suggestions?

Thanks,

- Stevan



$obj.meta.add_method('foo' = ???)

2005-08-09 Thread Stevan Little

More MOP related questions :)

In the p5 MetaModel, you can do the following:

$obj-meta-add_method('foo' = 
Perl6::Method-create_instance_method(sub { ... }));
$obj-meta-add_method('foo' = Perl6::Method-create_class_method(sub 
{ ... }));
$obj-meta-add_method('foo' = Perl6::Method-create_submethod(sub { 
... }));
$obj-meta-add_method('foo' = 
Perl6::Method-create_private_method(sub { ... }));


quick aside for clarity

The Perl6::Method package is really just a closure generator. It takes 
a chunk of code (a sub {} ref) and wraps it with the appropriate 
wrapper based on the type of method-thing you request. It currently 
handles instance methods, class methods, private methods and 
submethods. The details of this are not really relevant to this 
discussion though, I just wanted to answer what I saw as an inevitable 
question.


/quick aside for clarity

Now I realize that in perl 6 you can re-open classes and add methods to 
them. However this is not convenient for programmatic class generation. 
And I would really prefer the old Perl 5 way of mucking with the symbol 
table not be the Perl 6 way of doing this. The ideal approach IMO is to 
be able to do what the p5 MetaModel prototype does, and be able to add 
methods to the metaclass instance directly (which then exposes them to 
the class and instances of the class).


So, how should this look in Perl 6? I currently have a two 
thoughts/suggestions/directions.


1) Anonymous methods/submethods

$obj.meta.add_method('foo' = method (Foo $self: $bar) { ... });# 
adding an instance method
$obj.meta.add_method('foo' = method (::Foo $class: $bar) { ... }); # 
adding a class method
$obj.meta.add_method('foo' = submethod ($self: $bar) { ... }); # 
adding a submethod method
$obj.meta.add_method(':foo' = method ($self: $bar) { ... });   # 
adding a private method (NOTE: ':' in name)


I am not sure if anonymous methods have been discussed already or not. 
But this is one possible approach. The idea being that since it is a 
method already, it would already know about things like $?SELF, $?CLASS 
and next METHOD (although those values would be unbound), and would 
likely have an invocant parameter (which could sometimes be used to 
determine if it was a class method or instance method).


2) Closure factory

$obj.meta.add_method('foo' = sub ($self, $bar) { ... }, 
:typeinstance);

$obj.meta.add_method('foo' = sub ($self, $bar) { ... }, :typeclass);
$obj.meta.add_method('foo' = ($self, $bar) - { ... }, 
:typesubmethod);

$obj.meta.add_method(':foo' = { ... }, :typeprivate);

Given an arbitrary block of executable code (anything from a raw block, 
to a pointy block, to a sub ref) the add_method closure factory will 
turn it into the right method-thing based upon the :type parameter.


Thoughts??

Thanks,

Stevan




  1   2   >