On 7/22/05 11:37 AM, Larry Wall wrote:
> The problem I have with "is private" is that, while there may very
> well be a trait of that name that you can interrogate, I really
> want people to think of the private methods as being in a different
> namespace so that there's no confusion about the fact that you can
> have a private method and a public method of the same name.

Er, but can you ever have a public method that begins with an underscore
under your new system?  If not, then there'd never be any of the overlap
that you want people not to be confused about.  See, now I'm confused...

I get this part:

> The problem with
> 
>     $?SELF.:foo()
> 
> is that people see that as a .: operator on the foo method.

and like I said, I'm not insistent on using the colon.  But I would like to
find a way to remove the proposed contextual magic of the leading underscore
and replace it with something a bit more explicit and obvious--in both the
calling syntax and the declaration syntax.

So, the problem looks like this.  We want to find a way to:

* Define a private rw attribute named "foo" with an auto-generated
  non-virtual accessor.

* Define a public rw attribute named "foo" with an auto-generated
  virtual accessor.

* Call both of the accessors above with no ambiguity between the calls,
  even though both attributes have the same name.

The proposed solution:

    # Define a private rw attribute named "foo" with an auto-generated
    # non-virtual accessor.
    has $_foo;

    # Define a private rw attribute named "foo" with an auto-generated
    # non-virtual accessor.
    has $.foo is rw;

    # Call both of the accessors above with no ambiguity between the calls,
    # even though both attributes have the same name.
    $?SELF._foo(); # private accessor
    $?SELF.foo();  # public accessor

kind of sidesteps the "same name" issue by, well, not giving both the
attributes the same name.  Instead of two attributes both named "foo", the
private one is now named "_foo".  This makes the accessor calls unambiguous,
but it doesn't really succeed in emphasizing the separateness of the private
and public namespaces.

Since my goal is to remove the "_" magic, I first have to find a way to
differentiate a "private rw attribute with an auto-generated non-virtual
accessor" from a "private rw attribute with no auto-generated accessor."  I
proposed some sort of trait for that earlier:

  # private rw, no accessors, not virtual, name lexically scoped
  has $foo;

  # private rw, rw accessor, not virtual, name class scoped
  has $foo is private;

where the "private" name is up for grabs.  Or it could be turned around:

  has private $foo;

The next problem to solve is how to differentiate the calls.  The colon is
out because it looks like an operator.  The attribute names are really both
"foo", so we can't use the accessor name itself to differentiate.

But both those two "foo"s are in separate namespaces, right?  That's why we
can have both of them in the same class.  So how do we indicate the
namespace separation in the call?  In the spirit of the (now dead?) SUPER::
from Perl 5, this immediately springs to mind:

    $?SELF.foo();          # public
    $?SELF.PRIVATE::foo(); # private

That's ugly and long, but at least it's clear.  And it doesn't look like an
operator, that's for sure.  How about some shorter alternatives:

    $?SELF.OWN::foo();
    $?SELF.MY::foo();

The bottom line, I think, is that if you really want private and public
accessors to live in totally different namespaces, you need to explicitly
namespace one or both of the calls.  Name mangling isn't enough.  For
example, imagine this:

  # private rw, no accessors, not virtual, name lexically scoped
  has $foo;

  # private rw, rw _foo accessor, not virtual, name class scoped
  has $foo is private;

  $?SELF.foo();  # public
  $?SELF._foo(); # private

A silly example, perhaps, but it does make two attributes both named "foo",
one public and one private.  The calls are disambiguated because the
auto-generated non-virtual accessor for the private attribute has a leading
underscore added to the actual attribute name--IOW, name mangling.  But now
look at this:

  # private rw, no accessors, not virtual, name lexically scoped
  has $foo;

  # private rw, rw _foo accessor, not virtual, name class scoped
  has $foo is private;

  has $._foo; # BOOM - compile-time error: method _foo() already exists

  method _foo { ... } # ditto

"Ah ha!" you say.  "Isn't that an example of the private interface
interfering with the public interface?"  Exactly--but AFAICT, the original
proposal suffers from the same problem!

  # private rw, no accessors, not virtual, name lexically scoped
  has $foo;

  # private rw, rw _foo accessor, not virtual, name class scoped
  has $_foo;

  has $._foo; # BOOM - compile-time error: method _foo() already exists

  method _foo { ... } # ditto

The point is, if you really want to the namespaces of the public and private
attribute accessors to be entirely isolated from each other, then you need
to use some sort of real namespacing system.  Name mangling with standard
identifier characters is not adequate.

-John


Reply via email to