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

Reply via email to