First off, I like the idea a lot. However, I think there is some
extraneous bloat in it:
> The defined permissions are:
>
> '!', which forces the method call to fail, without further ado L<[5]>, and
> '+', which makes the autoaccessor handle the call
> '~', which makes the autoaccessor fail, but allow traditional ways
> of handling the method call..
>
> The default is '+', if no permission is specified for a context.
I completely miss the point of these. Isn't '!' the same as not
specifying ':accessible', since the autoaccessor method therefore won't
exist and either the defined class one or AUTOLOAD will still be called?
And isn't '+' the same as specifying ':accessible'? And how could you
ever use '~'?
If I have a piece of code (I'll use :access because it's a lot shorter):
# ...
$self->{name} : access = "Nate";
# ...
sub name {
# ...
}
Then just specifying ':access' should cause it to override name(), which
is in Perl already ("subroutine name() redefined..."). If I then drop
the ':access', name() will be called. And if name() didn't exist, then
AUTOLOAD would be called. The !,+,~ permissions uselessly duplicate
this, as far as I can tell.
> A context with a '~' permission is the same as not specifying the
> context letter at all L<[7]>, and is included only for completeness.
>
> The context can be:
>
> 'r' for rvalue (or 'r' for read)
> 'l' for lvalue (or 'w' for write)
> 'm' for mutator (which has no synonym) L<[6]>
I don't see why you'd want to restrict l/r sides if they're hash keys.
This is implicit in making them readonly. If the user tries to use a
readonly variable in an lvalue assignment, then it's an error. And
telling them they can't use a writeable value on the l side makes that
readonly implicitly.
So I would drop this, it's unnecessary and complex. All of it is taken
care of by a :constant keyword. Just include a :constant attribute for
those things you want readonly:
$self->{DEFAULT_DIR} : access, constant = '/usr/bin';
$self->{name} : access = "Nate";
$self->{peers} : access = undef;
That is a lot simpler and seems to feel a lot better. Note again I
chopped it to 'access' to save typing. It also seems to accomplish the
same thing, unless I'm missing something huge.
I think the idea's great, but I think the only thing it needs to do is
introduce a new ':access' attribute which basically just makes it
possible to drop {}'s in access calls. The other stuff can be handled by
combinations with other RFC's and existing Perl stuff.
Finally, one thing that you should address is how to handle multi-level
hashes:
$self->{CONFIG}->{DEFAULT_DIR} : access, constant = '/usr/bin';
$self->{STATE}->{name} : access = "Nate";
$self->{STATE}->{peers} : access = undef;
Which is how I store data internally in my modules. Seems to me that you
could make Perl Do The Right Thing by implicitly remembering the proper
hash level:
$self->DEFAULT_DIR # $self->{CONFIG}->{DEFAULT_DIR}
$self->peers # $self->{STATE}->{peers}
$self->name # $self->{STATE}->{name}
Then, if someone defined the same end node in multiple levels and tried
to use ':access' on both of them, simply issue a "subroutine
DEFAULT_DIR() redefined at line..." warning.
$self->{CONFIG}->{DEFAULT_DIR} : access, constant = '/usr/bin';
$self->{STATE}->{DEFAULT_DIR} : access; # "sub redefined" warning
-Nate