What if Perl OO was a Core Feature?
Over on Reddit /r/perl, there's a rather blatant troll complaining about the lack of OO as a core feature in Perl. The tone there is clearly not constructive and not worth responding further, but I feel compelled to answer a question: what would be improved if OO was a core feature, rather than built out of existing components of the language?
Personally, I think the fact that OO can be built this way is a demonstration of flexibility. It also allows you to build your own OO system that suits your needs. If the standard kind of blessed data structure doesn't work for you, try Inside-Out Objects. This also had hidden benefits later on; when roles/traits/mixins became all the rage, Perl just added them via CPAN modules. There was no long, drawn out, design-by-committee bikeshedding discussion like there was for Java.
If you really wanted to, you could even build an object system without bless()
or packages. The constructor would return a hash, which is filled with sub references:
sub new_object { my %object = ( foo => sub { 'foo' }, bar => sub { 'bar' }, baz => sub { 'baz' }, ); return %object; } my %obj = new_object; say $obj{foo}->(); # Prints 'foo'
Inheritance is a matter of a different constructor calling the original constructor, then filling in different subrefs:
sub new_inherit_object { my %object = new_object(); $object{foo} = sub { 'override foo' }; $object{qux} = sub { 'qux' }; return %object; } my %obj = new_inherit_object; say $obj{foo}->(); # Prints 'override foo'
(No, I don't really suggest doing this. It's just an interesting exercise in building an object system using limited language components. Although this isn't too far from how JavaScript builds objects.)
Getting back to the usual bless()
system, there is a drawback: the learning curve. Think of all the things you have to grasp before you can understand Perl OO. There's subroutines, passing arguments to subroutines, and putting those subroutines into packages. Any bless
'd object is going to be a complex data structure, and before you can figure those out, you need to grasp references. Even for somebody experienced in another programming language, that's a lot to ask before you can get them up to speed on object programming. It's even harder for somebody with no programming background at all.
Moose somewhat alleviates this. It can hide a lot of the details of the complex data structure, though obviously you're going to need to dig into that at some point. The constructors in Moose can also do sensible things for you. It's a lot better than Java, where the constructors tend to have a lot of this.foo = foo;
statements to set private member variables from the arguments.
What Moose can't fix is subroutines. Sub signatures are a sore spot for Perl. I think it really is an embarrassment that we still have this problem in 2013. And we need signatures down pat before we can even start thinking about multi-method dispatch.
[Via my blog]
If OO becomes part of the core of Perl, I'll learn a new language. The only part of OO that's worth anything is encapsulation and Perl does that with packages. Inheritance is a distraction; Perl already does polymorphism; and code reuse, even in a 100% OO language, is most often copy & paste. There is no advantage to crippling Perl by forcing OO on everything.
Timm, you might be interested to learn about my current project, p5-mop which is exactly what you are talking about, a proposal for a new object system for the Perl 5 core. It is currently only in prototype stages, but soon (next thursday to be exact) myself and the other developers will be hashing out exactly what needs to happen to put it into core. (BTW - we are always looking for help and people willing to kick the tires by porting modules, come over to #p5-mop on irc.perl.org and we will be happy to get you started).
As for sub signatures, that is being worked on too, by Peter Martini (here is a video of his YAPC::NA talk). I actually just had lunch with Peter earlier week to discuss where he is on the project and what, if any, are his blockers (none really, only time at this point).
shawncorey - just because the core gets an improved OO system does not mean that OO will invade all of Perl. In fact, just the opposite, part of why it has taken so long to get a new OO system and subroutine signatures is because of the strict commitment to backwards compatibility that Perl has.
Fear not, no one will ruin the Perl you know and love with new features, the new will simply live along side the old.
Oh, yes, I know about p5-mop and Peter's talk. I just wanted this post to be more of an abstract answer.
I was thinking of porting UAV::Pilot from Moose to p5-mop. I haven't made a full-version-number release yet, and I'm reserving the right to make API-breaking changes until then. I might drop by the IRC room sometime.
Stevan Little -- "Once you start down the dark path, forever will it dominate your destiny."
I simply don't believe that once OO is added to Perl, the religious fanatics won't insist OO for everything.
Agree with @shawnhcorey - current perl "bless system" covers 99% of my needs. I don't feel like I need new OO.
Surely the existence of the current "bless system" as you call it, proves this point wrong. The current "bless system" has been there for ages, yet we're not using it for everything.
I wonder what parts of OO are said to be not core part Perl. The terminology may differ from other languages (e.g. translate "package" to "class" and "blessed reference" to "instance") but it's all there and documented.
I suppose complaints are less about missing features but about the complexity to make use of them. For instance there should have been a 'method' keyword since years to allow writing 'method foo { ... }' as shortcut for 'sub foo { my $self = shift; ... }'. These complaints are justified, however it's not about OO features but about their usability.
OO is already becoming a core feature of Perl. And this is a new programming language called Perl 6.
« Forcing OO on everything » is not in the Perl culture. Perl is not Java. Perl has instead a strong culture of mixing programming paradigms (« There is more than one way to do it ») and this is preserved in Perl 6, improving the support for existing ones, and adding more (such as parallel processing).
@Toby Inkster -- my point is that OO should not be used for everything.
@Stevan Little -- see above comment about OO fanatics insisting that OO be use for everything.
@Olivier Mengué -- You will note how popular Perl 6 is.
Toby Inkster gave an excellent answer.
This "if OO will be easy and integral, people will force it upon me everywhere, all the time" claim is not just silly, but it's absurd and unfounded. It's actually just FUD.
Toby pointed at the bless mechanism, which people don't force upon everything.
Preventing a modern feature because someone might ask you to use it when you don't want to is a terrible reason not to do it. It's fucking 2013, the Fortran people are laughing at us.
@shawncorey - It should be just as simple to ignore OO fanatics with p5-mop in core as it is to ignore them now. I do not think that having a better OO system in the core will change that.
This is Perl after all, TIMTOWTDI will **ALWAYS** be the core of the language.
That is not simple?
shawncorey - No, it is not. Allow me to explain the reasons why. (NOTE: I am going to explain this from the perspective of someone who didn't learn OO from Perl)
1) It confuses class methods and instance methods by having &new in the same namespace as other methods.
2) It accepts anything you give it for attribute values with no checking at all. Even if you don't want that strictness, it still loses out on self-documentation, meaning, I have no idea what your expected attributes are.
3) While it sort of handles inheritance by allowing #2, it does not handle object initialization at all (and every subclass that is made will have to handle it explicitly (and hopefully they will all do it right way)).
4) Classes share the same namespace as a package, this means imported utility functions can be called as methods even if they make no sense to be called as such.
5) Methods are just subroutines, they only differ in the way that they are called (and can be called either way).
6) Inheritance is defined by populating a specifically named package variable with a string which will, at runtime, be looked up to find if it corresponds to another package that has been loaded.
7) The instance structure itself is indistinguishable from (and has the same interface as) a non-instance HASH reference, meaning it can be easily be mistaken as such and have it's encapsulation violated.
Now, don't get me wrong, I believe there is an elegant simplicity to Perl's OO system. That said, it simply requires too much boilerplate to just get off the ground, much less use on a reasonable scale. The fact is that you are missing a lot in your example, the full version would look like this:Whereas I am proposing that you instead would just have to write this: To get the exact same result. Now, really, which is simpler? Which is more obvious to someone not already steeped in the ways of Perl OO programming?
"sub new" is not a constructor, it is only the most commonly used name for factory methods; perl OOP does not come with constructors. Why should "new" be in a separate namespace ?
OO is in core Perl: bless is in the core, unless I am mistaken;
'This "if OO will be easy and integral, people will force it upon me everywhere, all the time" claim is not just silly, but it's absurd and unfounded. It's actually just FUD.'
OO is easy and integral in Perl already, and is forced upon us everywhere, whether it makes sense or not, but it is our duty to resist such pressures when we think it does not make sense :); crippling Perl for this reason does not make sense, though it might make sense to mark the new OOP schemes as "experimental" for a couple of releases after they get in the official core.