| selfvars documentation | Contained in the selfvars distribution. |
selfvars - Provide $self, @args, %opts and %hopts variables for OO programs
package MyClass;
### Import $self, @args, %opts and %hopts into your package:
use selfvars;
### Or name the variables explicitly:
# use selfvars -self => 'self', -args => 'args', -opts => 'opts', -hopts => 'hopts';
### Write the constructor as usual:
sub new {
return bless({}, shift);
}
### Use $self in place of $_[0]:
sub foo {
$self->{foo};
}
### Use @args in place of @_[1..$#_]:
sub bar {
my ($foo, $bar) = @args;
$self->{foo} = $foo;
$self->{bar} = $bar;
}
### Use %opts in place of %{$_[1]}:
sub baz {
$self->{x} = $opts{x};
$self->{y} = $opts{y};
}
### Use %hopts with $obj->yada( x => 1, y => 2 ) call syntax
sub yada {
$self->{x} = $hopts{x}
$self->{y} = $hopts{y}
}
This module exports four special variables: $self, @args, %opts and %hopts.
They are really just handy helpers to get rid of:
my $self = shift;
Behind the scenes, $self is simply tied to $_[0], @args to
@_[1..$#_], %opts to %{$_[1]}, and %hopts% to %{{@_[1..$#_]}}.
Currently, $self, @args and %hopts are read-only; this means you cannot
mutate them:
$self = 'foo'; # error
my $foo = shift @args; # error
$hopts{x} = 'y'; # error
delete $hopts{x}; # error
This restriction may be lifted at a later version of this module, or turned into a configurable option instead.
However, %opts is not read-only, and can be mutated freely:
$opts{x} = 'y'; # okay
delete $opts{x}; # also okay
Returns the current object.
Returns the argument list.
Returns the first argument, which must be a hash reference, as a hash.
Returns the arguments list as a hash.
You can choose alternative variable names with explicit import arguments:
# Use $this and @vars instead of $self and @args, leaving %opts and %hopts alone:
use selfvars -self => 'this', -args => 'vars', -opts, -hopts;
# Use $this but leave @args, %opts and %hopts alone:
use selfvars -self => 'this', -args, -opts, -hopts;
# Use @vars but leave $self, %opts and %hopts alone:
use selfvars -args => 'vars', -self, -opts, -hopts;
You may also omit one or more variable names from the explicit import arguments:
# Import $self but not @args, %opts nor %hopts:
use selfvars -self => 'self';
# Same as the above:
use selfvars -self;
# Import $self and %opts but not @args nor %hopts:
use selfvars -self, -opts;
None.
This module was inspired and based on Kang-min Liu (gugod)'s self.pm.
As seen on #perl:
<gugod> audreyt: selfvars.pm looks exactly like what I want self.pm to be in the beginning
<gugod> audreyt: but I can't sort out the last BEGIN{} block like you did.
<gugod> audreyt: that's a great job :D
唐鳳 <cpan@audreyt.org>
To the extent possible under law, 唐鳳 has waived all copyright and related or neighboring rights to selfvars.
This work is published from Taiwan.
| selfvars documentation | Contained in the selfvars distribution. |
package selfvars; use 5.005; use strict; use vars qw( $VERSION $self @args %opts %hopts ); BEGIN { $VERSION = '0.32'; } sub import { my $class = shift; # Oooh, the irony! my %vars = (-self => undef, -args => undef, -opts => undef, -hopts => undef) unless @_; while (@_) { my $key = shift; if (@_ and $_[0] !~ /^-/) { $vars{$key} = shift; } else { $vars{$key} = undef; } } my $pkg = caller; no strict 'refs'; my %map = (self => \$self, args => \@args, opts => \%opts, hopts => \%hopts); while (my ($sym, $var) = each %map) { exists $vars{"-$sym"} or next; $vars{"-$sym"} = $sym unless defined $vars{"-$sym"}; *{"$pkg\::$vars{qq[-$sym]}"} = $var; } } package selfvars::self; sub TIESCALAR { my $x; bless \$x => $_[0]; } sub FETCH { my $level = 1; my @c = (); while ( !defined( $c[3] ) || $c[3] eq '(eval)' ) { @c = do { package DB; @DB::args = (); caller($level); }; $level++; } $DB::args[0]; } sub STORE { require Carp; Carp::croak('Modification of a read-only $self attempted'); } package selfvars::args; use Tie::Array (); use vars qw(@ISA); BEGIN { @ISA = 'Tie::Array' } sub _args { my $level = 2; my @c; while ( !defined( $c[3] ) || $c[3] eq '(eval)' ) { @c = do { package DB; @DB::args = (); caller($level); }; $level++; } \@DB::args; } sub readonly { require Carp; Carp::croak('Modification of a read-only @args attempted'); } sub TIEARRAY { my $x; bless \$x => $_[0] } sub FETCHSIZE { scalar $#{ _args() } } sub STORESIZE { goto &readonly } # $#{ _args() } = $_[1] + 1; sub STORE { _args()->[ $_[1] + 1 ] = $_[2] } sub FETCH { _args()->[ $_[1] + 1 ] } sub CLEAR { goto &readonly } # $#{ _args() } = 0; sub POP { goto &readonly } # my $o = _args(); (@$o > 1) ? pop(@$o) : undef sub PUSH { goto &readonly } # my $o = _args(); push( @$o, @_ ) sub SHIFT { goto &readonly } # my $o = _args(); splice( @$o, 1, 1 ) sub UNSHIFT { goto &readonly } # my $o = _args(); unshift( @$o, @_ ) sub DELETE { goto &readonly } # my $o = _args(); delete $o->[ $_[1] + 1 ] sub SPLICE { goto &readonly } # my $ob = shift; # my $sz = $ob->FETCHSIZE; # my $off = @_ ? shift : 0; # $off += $sz if $off < 0; # my $len = @_ ? shift : $sz - $off; # splice( @$ob, $off + 1, $len, @_ ); BEGIN { local $@; eval q{ sub EXISTS { my $o = _args(); exists $o->[ $_[1] + 1 ] } } if $] >= 5.006; } package selfvars::opts; sub _opts { my $level = 2; my @c; while ( !defined( $c[3] ) || $c[3] eq '(eval)' ) { @c = do { package DB; @DB::args = (); caller($level); }; $level++; } $DB::args[1]; } sub TIEHASH { my $x; bless \$x => $_[0] } sub FETCH { _opts()->{ $_[1] } } sub STORE { _opts()->{ $_[1] } = $_[2] } sub FIRSTKEY { my $o = _opts(); my $a = scalar keys %$o; each %$o } sub NEXTKEY { my $o = _opts(); each %$o } sub EXISTS { my $o = _opts(); exists $o->{$_[1]} } sub DELETE { my $o = _opts(); delete $o->{$_[1]} } sub CLEAR { my $o = _opts(); %$o = () } sub SCALAR { my $o = _opts(); scalar %$o } package selfvars::hopts; sub _opts { my $level = 2; my @c; while ( !defined( $c[3] ) || $c[3] eq '(eval)' ) { @c = do { package DB; @DB::args = (); caller($level); }; $level++; } shift @DB::args; @DB::args; } sub readonly { require Carp; Carp::croak('Modification of a read-only %hopts attempted'); } sub TIEHASH { my $x; bless \$x => $_[0] } sub FETCH { my (%o) = _opts(); $o{ $_[1] } } sub STORE { goto &readonly } sub FIRSTKEY { my (%o) = _opts(); my $a = scalar keys %o; each %o } sub NEXTKEY { } sub EXISTS { my (%o) = _opts(); exists $o{$_[1]} } sub DELETE { goto &readonly } sub CLEAR { goto &readonly } sub SCALAR { my (%o) = _opts(); scalar %o } package selfvars; BEGIN { tie $self => __PACKAGE__ . '::self'; tie @args => __PACKAGE__ . '::args'; tie %opts => __PACKAGE__ . '::opts'; tie %hopts => __PACKAGE__ . '::hopts'; } 1; __END__