in reply to Re^11: Data Structures
in thread Data Structures
Starting at the end (cos the the challenge was interesting:).
Sub::Exporter on the other hand is awesome. ... but it can do all sorts of fun tricks. You couldn't do this with Exporter:
Who needs Exporter :)
package LOLCat; use pudu 'has' => { -as => 'i_can_haz' }; i_can_haz 'cheeseburger' => ( is => 'rw', trigger => sub { print "NOM NOM" } ); 1;
#! perl -slw use strict; use LOLCat; LOLCat->new->cheeseburger('KTHNXBYE'); __END__ c:\test>t-pudu.pl NOM NOM
And what is actually required inside pudu.pm to make that happen?
package pudu; use strict; use warnings; use constant Exportables => { has => { -as => 'has' }, new => { -as => 'new' } }; my @attrs = (); sub _exportTo { no strict qw[ refs ]; *{ $_[0] . '::' . $_[ 1 ] } = $_[ 2 ]; } sub new { my $class = shift; die "Uneven attribute list (Missing value?(use 'undef')" if @_ & 1 +; my %args = @_; return bless \@attrs, $class; } sub has { my $package = caller; my $name = shift; my %attr = @_; $attrs[ @attrs ] = \%attr; my $slot = eval qq[ sub(){ ${ \$#attrs } } ]; _exportTo( $package, $name, sub :lvalue { $_[ 0 ][ &$slot ]{ trigger }->( $_[ 0 ], $_[ 1 ] ) if $_[ 0 ][ &$slot ]{ trigger }; $_[ 0 ][ &$slot ] } ); } sub import { my $class = shift; die "Uneven parameter list (Symbol without alias?)" if @_ & 1; my %args = ( %{ +Exportables }, @_ ); my %exports; @exports{ keys %{ +Exportables } } = delete @args{ keys %{ +Export +ables } }; warn "Unknown export(s) @{[ keys %args ]} ignored" if %args; my $package = caller; while( my( $export, $alias ) = each %exports ) { _exportTo( $package, $alias->{ -as }, \&$export ); } } 1;
It's minimal, just enough to meet the requirements of the challenge, but I hope it is enough to show that much of what Moose does, could be met without large dependency chains, and rather more efficiently. (Especially once you drop the need for bondage and discipline!)
I guess that sums up my feelings about a lot of this kind of module. (Sub::Exporter et al.) At their core, they provide a single, useful mechanism. But then, almost inevitably, they feel the need to add to that basic mechanism a bunch of "fun tricks", which whilst fun, often aren't required by most of their users. And the provision of those additional features, as much for the sake of having something to put in the POD as anything else, leads to complexity and bloat. Not just because of the presence of the additional code to provide those extra, little-used features. But also in additional code in the core, oft-used features in order to support the little used ones. With the result that code that only needs the core, useful mechanisms is often paying a penalty for the support of features that they don't use.
For the authors of these modules, they only test & benchmark their code from one level above, and the penalty seems minor. But once you get to the level of a complex framework like Moose, that utilises several of this type of module, and uses two, three & four levels deep chains of them, each adding its own layer of "fun tricks" and their associated (unnecessary) overhead, the individually small deltas start to add up.
Now imagine me writing my graphics application using Moose. I have a hierarchy of classes: Solids inherit from WireFrames inherit from Lines inherit from Point3D; and the core of my application is doing hidden Line and hidden Face removals on complex Solids before rendering to a View2D--the very stuff where Class/Object mechanisms like Moose are at their most useful and productive. And at each layer of my application I'm picking up the products of the deltas below Moose and compounding them over the layers of my application above Moose.
The result is that small, negative performance delta don't just add up, but multiply up, and my app is running 2 or 3 or 4 times more slowly because of the presence of features in the lowest levels that I, nor most other Moose users will ever use.
tos recently posted a behemoth of a piece of really quite awful code. (No disrespect meant tos. Its given me hours of fun exploring it). It sets out to be OO, but throws everything into one huge file because he's taken a bunch of short cuts (global vars mainly) to work around things he didn't understand how to do using Perl's DIY OO mechanisms. I had a couple of attempts at splitting it up into modules and making it work, but never really had the motivation to see it through.
It runs a 3D Rubix Cube (3x3, 4x4 or 5x5) simulation using Tk as the display tool, making extensive use of OO (mostly) to perform the math. It runs, in its presented, messy, badly structured form, with a surprising turn of speed. You can spin and rotate the cube in 3 dimensions using the mouse, and (when it doesn't crash) the graphics keep up with you.
The challenge is for us to agree the Moose-style class definitions for the 8 classes required by the Rubix Cube application:
package matob; package point3d; package line3d; package vec3d; package rect3d; package cube3d; package slice; package qb;
and then you port it to Moose and I'll extend pudu just enough to meet that specification. We could then compare, from all aspects, the results.
I realise that this is more than just a couple of hours work and that you're a busy guy, busy doing $work and maintaining Moose. But the results would make for a very good demonstration of the power of Moose (he said trying to tempt :).
(*)I mentioned "bondage & discipline" above. I realise that this is what a lot of your customers are asking for, and you are supplying that need. I did start to question that need here, but decided that it was irrelevant to the subject and besides, I feel a meditation on the subject coming on, so I've deferred that for another thread. And for the record. The more I learn about what Moose does (and the way it does it for the most part), the more impressed and enthralled I am by it. I'm even more impressed by what you and your team have pulled together so quickly.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^13: Data Structures
by stvn (Monsignor) on May 23, 2008 at 21:42 UTC | |
by BrowserUk (Patriarch) on May 23, 2008 at 23:07 UTC | |
by stvn (Monsignor) on May 24, 2008 at 04:28 UTC | |
by BrowserUk (Patriarch) on May 24, 2008 at 06:15 UTC |