I like a lot of what is in this RFC. It rings true for me, since my favorite CPAN
modules are OO. The less I need to learn about a package, the happier I tend to be.
Also, powerful objects tend to be slower (though it's getting better).
I haven't seen all of the discussion reguarding this RFC, but I'll make comments on
the following <<EOS:
class Person;
our $debug = 0;
my ( $name, $race, @aliases );
package main;
$Person->debug = 1;
my $mage = Person->new(
name => 'Gnadalf'',
race => 'Istar',
aliases => [ qw( Mithrandir Olorin Incanus ) ]
);
EOS
This poses some problems with the use of my, in in terms of closure. It breaks
compatibility. I would recommend using a pragma similar to 'fields' such as
'attributes', or to at least make it it's own keyword. Flexibility is the key with
perl, and what you're suggesting actually reduces some of the features of perl for
this special context of execution.
Also, the distinction between packages and classes get's hairy. How does the compiler
distinguish
# file1.pm
package Person;
our $debug;
#file2.pm
class Person;
my ( $name, $race, @alises );
#main.pl
use file1;
use file2;
Since package can allow you to arbitrarily flip back and forth, this is a real issue.
Do we assume that if any package is defined as a class, then all are? The implication
is in the implementation of the "magic". Also, how does this work if we say:
package Person;
my ( $name, $rac, @aliases );
package main;
my $obj = Person->new();
print keys %Person;
I suggest that if there is a seperate 'class' keyword, that it should merely be an
internal alias as in:
class Person;
class Wizard isa Person;
becomes:
BEGIN {
package Person;
use base qw( CLASS );
.. # any other magic
}
BEGIN {
package Wizard;
use base qw( Person );
...
}
And this global CLASS package will pre-define 'new', and autoload in such a way that
your stated optimizations can occur. Making such an alias isn't so far fetched.. Look
at 'use' verses 'require'.
As for member variables being defined by "my". I see little or no value (especially
in light of closure compatibility), and still support the:
use fields qw( name race aliases ). Alternatively, we could make use of a 'fields'
keyword. For perl5 compatibility, you'd probably choose a slightly different name so
you could achieve use perl6fields qw( $name $race @aliases ), in much the same way as
use vars qw( .... ).
I do like the continued use of "_" for private variables. I see no reason to enforce
their privacy (keeping with perl's general open policy). The advantage of keeping
them open is the use of debugging. If you OO folks are adament, then a flag / pragma
could enforce privacy through warns, at the developer's discression.
I would suggest that positional parameters are a definate no-no for the default 'new'
constructor. It's the same as using "*" in DB design. Someone could re-order the
parameters in the definition without telling anyone (or even add attributes ) and
you'd be screwed. I'm biased however, since I use hashes for just about everything (
even one-value parameters ).
As for scope issues. What I think would go on is the following:
Currently, scope works something like this:
sub getVal {
if ( exists $caller_stack[ $stack_level ]->lexical{ $var_name }{ $var_type } ) {
return $context->lexical{ $var_name }{ $var_type };
} else {
return $packages{ $package }->globals{ $var_name }{ $var_type };
}
} # end getVal
And similarly with setVal.
In the proposed class-variables, we'd have:
sub getVal {
if ( exists $caller_stack[ $stack_level ]->lexical{ $var_name }{ $var_type } ) {
return $context->lexical{ $var_name }{ $var_type };
} elsif ( exists $packages{ $package }->class_variables{ $var_name }{ $var_type } ) {
return $packages{ $package }->class_variables{ $var_name }{ $var_type };
} else {
return $packages{ $package }->globals{ $var_name }{ $var_type };
}
} # end getVal
Essentially this adds a layer to variable references.. Shouldn't be that hard, but
slows general access down a bit for globals. OO in perl5 was an extension. Here it
makes it's way into the core in a major way.
Next is a small issue with constructors / destructors. I'm not exactly sure why you
were suggesting 'NEW', 'OLD' to replace the explicit and generic constructor along
with the implicit DESTROY. I don't see any problem with implicitly using 'new'. OLD
would either have to replace DESTROY, or run in tandom with it, which I see no value
in. By making all 'classes' inherit 'CLASS' ( the OO version of CORE ), then we can
continue to treat chained-constructors just as in perl5.
The following would be a good start for CLASS:
package CLASS;
our ( ... ); # any global flags
attributes ( $me );
sub new {
my $class = shift;
$me = fields::new( $class );
my %args = @_;
$me->{$var} = $args{ $var } for keys %args;
return $me;
} # end new
sub autoloader {
... # do magic here
} # end autoloader
sub INSPECT { ... }...
... # all other CLASS-specific automagic methods.
This could be optimized internally (especially in the lexical mapping of
class-variables).
-Michael