Last active
December 27, 2015 06:49
-
-
Save BenGoldberg1/7284889 to your computer and use it in GitHub Desktop.
Defines an alternative boilerplate for class methods.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!perl | |
package Alias::Shift; | |
require Devel::LexAlias; | |
use strict; | |
use warnings; | |
my $skip; | |
sub shifter { | |
my ( $pack, $ref, @attr ) = @_; | |
if ( my @bad = grep $_ ne 'shift', @attr ) { | |
return @bad; | |
} | |
unless ( defined $skip ) { | |
$skip = 0; | |
++$skip while caller($skip) ne 'attributes'; | |
++$skip; | |
} | |
{ package DB; caller($skip); } | |
unless (@DB::args) { | |
require Carp; | |
Carp::croak('Cannot shift from @_, when @_ is empty!'); | |
} | |
my $val = CORE::shift(@DB::args); | |
Devel::LexAlias::alias_r( $val, $ref ); | |
} | |
no warnings 'once'; | |
*MODIFY_HASH_ATTRIBUTES = \&shifter; | |
*MODIFY_ARRAY_ATTRIBUTES = \&shifter; | |
*MODIFY_SCALAR_ATTRIBUTES = \&shifter; | |
1; | |
__END__ | |
Quick Example Usage: | |
package MyPack; | |
use parent qw(Alias::Shift); | |
sub new { | |
my ($class, %args) = @_; | |
bless \%args, $class; | |
} | |
sub foo { | |
my %self : shift; | |
++$self{bar}; | |
} | |
1; | |
__END__ | |
Basically, this is an alternative to doing: | |
sub foo { | |
my $self = shift; | |
++$self->{bar}; | |
} | |
It saves some typing (if you ignore the use parent ...) and | |
makes your code look a little bit cleaner. Obviously it's | |
not nearly as fast as normal code, since shifter gets called | |
at runtime for every lexical with the :shift attribute, but | |
if someone with better knowledge of perl's internals were to | |
take a whack at it, it ought to be possible to write: | |
sub foo : shift(%self) { | |
++$self{bar}; | |
} | |
The attribute would modify the subroutine (at compile time), | |
to insert code into &foo, eqivilant to alias_r( \(my %self), shift ). | |
Even cooler, imho, would be something like: | |
use Attribute::CPPish; | |
sub foo :CPPish (%self $bar) { | |
++$bar; | |
} | |
Which would create lexicals for %self and $bar, where %self | |
is gotten by shifting @_, and $bar is a lexical which is aliased | |
to $self{bar}. | |
But that's very much beyond my coding skills. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment