These points are not covered in the Moose documentation:
Question: If you set an attribute in the constructor, does it override the builder?
Answer: Yes, the builder is not run.
Code:
perl -MMoose -le'package Quxx; use Moose; has "qux" => ( is => "ro", builder => "_build_qux" ); sub _build_qux { die "duck" }; package main; my $q = Quxx->new( qux => "cat" ); print "qux = #".$q->qux."#"'
Output:
qux = #cat#
Question: How do you compose a writer subroutine? (aka setter / mutator method).
Answer: You don't need to, Moose creates it for you. Just define it in the attribute and then call it.
Code:
perl -MMoose -le'package Foo; use Moose; has "foo" => ( is => "rw", writer => "_set_foo" ); sub set_foo { "bar" }; sub bar { my $self = shift; $self->_set_foo(2); }; package main; my $f = Foo->new; $f->bar(4); print "foo = #".$f->foo."#"'
Output:
foo = #2#
A piggy bank of commands, fixes, succinct reviews, some mini articles and technical opinions from a (mostly) Perl developer.
Jump to
Showing posts with label moose. Show all posts
Showing posts with label moose. Show all posts
Manual automatic accessors in Perl
If you don't have Moose, Mo* or Class::Accessor:
package Foo;
=head1 SYNOPSIS
my $f = Foo->new(
bar => 'rab',
qux => 'xuq',
);
=cut
use constant ACCESSOR_MAP => {
'get_bar' => 'bar',
'get_qux' => 'qux',
};
use constant ACCESSOR_ITEM => qw(ping ting zing);
sub new {
my ( $c, %args ) = @_;
my $class = ref $c || $c;
bless {%args}, $class;
}
sub __mk_accessor {
my ( $c, $name, $key ) = @_;
$key ||= $name;
my $pkg = ref $c || $c;
my $sym = join( '::', $pkg, $name );
no strict 'refs';
*{$sym} = sub {
my ($self) = @_;
$self->{$key};
};
}
# set up ping(), ting(), zing()
__PACKAGE__->__mk_accessor($_) foreach __PACKAGE__->ACCESSOR_ITEM;
# set up get_bar(), get_qux()
for my $k ( keys %{ __PACKAGE__->ACCESSOR_MAP } ) {
my $v = __PACKAGE__->ACCESSOR_MAP->{$k};
__PACKAGE__->__mk_accessor( $k, $v );
}
package Foo;
=head1 SYNOPSIS
my $f = Foo->new(
bar => 'rab',
qux => 'xuq',
);
=cut
use constant ACCESSOR_MAP => {
'get_bar' => 'bar',
'get_qux' => 'qux',
};
use constant ACCESSOR_ITEM => qw(ping ting zing);
sub new {
my ( $c, %args ) = @_;
my $class = ref $c || $c;
bless {%args}, $class;
}
sub __mk_accessor {
my ( $c, $name, $key ) = @_;
$key ||= $name;
my $pkg = ref $c || $c;
my $sym = join( '::', $pkg, $name );
no strict 'refs';
*{$sym} = sub {
my ($self) = @_;
$self->{$key};
};
}
# set up ping(), ting(), zing()
__PACKAGE__->__mk_accessor($_) foreach __PACKAGE__->ACCESSOR_ITEM;
# set up get_bar(), get_qux()
for my $k ( keys %{ __PACKAGE__->ACCESSOR_MAP } ) {
my $v = __PACKAGE__->ACCESSOR_MAP->{$k};
__PACKAGE__->__mk_accessor( $k, $v );
}
# not tested
Perl MooseX::Params::Validate gotcha
This error:
Parameter #1 ("1") to Some::Module::a_method did not pass the \'checking type constraint for Different::Module\' callback\n at /some/path/to/some/file/or/other.pm line 42
(but the parameters passed in are actually all correct)
...it could mean you forgot to shift off $self. pos_validated_list doesn't detect $self like validated_list and validated_hash do.
Parameter #1 ("1") to Some::Module::a_method did not pass the \'checking type constraint for Different::Module\' callback\n at /some/path/to/some/file/or/other.pm line 42
(but the parameters passed in are actually all correct)
...it could mean you forgot to shift off $self. pos_validated_list doesn't detect $self like validated_list and validated_hash do.
Labels:
error,
moose,
parameters,
perl
Parameter checking Perl
use MooseX::Params::Validate;
use MooseX::Types::Moose qw{ ArrayRef Int };
use MooseX::Types::Structured qw{ Dict };
use MooseX::Types::Common::Numeric qw{ PositiveInt PositiveOrZeroInt };
use MooseX::Types::Common::String qw{ NonEmptyStr };
sub some_method {
my ($self, $channel_id, $some_array_of_structs) = validated_list(
\@_,
channel_id => { isa => PositiveInt },
channel_name => { isa => NonEmptyStr },
some_array_of_structs => {
isa => ArrayRef[ Dict[
some_id => PositiveInt,
quantity => PositiveOrZeroInt,
cruciality => Int
] ]
}
);
# ...
}
Labels:
data,
moose,
parameters,
perl,
validation
Trace the execution of subroutines under mod_perl
1) First try one of these to trace every line (doesn't actually capture subroutine names):
Debug::Trace, Debug::LTrace, Devel::Trace, or others.
2) Then if you want to filter the list, try:
perl PERL5DB='sub DB::DB {my @c=caller;return if $c[1] =~ m|/opt/foo/bar| || $c[1] =~ m|/qux/| || $c[1] =~ m|Useless|; print STDERR qq|@c[1,2] ${"::_<$c[1]"}[$c[2]]|}' perl -d path/to/test/file.t
(thanks Brian)
3) Here's one I came up with using Moose:
use Moose;
use Scalar::Util;
use Data::Dumper;
for my $func qw(list all the subroutine names here) {
around $func => sub {
my $orig = shift;
my $self = shift;
warn "Running __PACKAGE__::${func} with:\n";
my $i = 0;
foreach my $param (@_) {
$i++;
# don't display class it$self
next if blessed $param and $param->isa(__PACKAGE__);
if (blessed $param) {
} else {
warn "\t$i = ".Dumper($param);
}
}
# call the original sub
$self->$orig(@_);
}
}
4) Simple way to log all parameters:
my $r=\@_; $logger->debug('entering ', sub { $logger->dump(args => $r) });
5) Simple way to log method name only, without potentially verbose parameters:
$logger->info("entering ".( caller(0) )[3]);
6) Log4perl configuration
Use %M to log the method name, then just log anything, e.g. "entering".
Debug::Trace, Debug::LTrace, Devel::Trace, or others.
2) Then if you want to filter the list, try:
perl PERL5DB='sub DB::DB {my @c=caller;return if $c[1] =~ m|/opt/foo/bar| || $c[1] =~ m|/qux/| || $c[1] =~ m|Useless|; print STDERR qq|@c[1,2] ${"::_<$c[1]"}[$c[2]]|}' perl -d path/to/test/file.t
(thanks Brian)
3) Here's one I came up with using Moose:
use Moose;
use Scalar::Util;
use Data::Dumper;
for my $func qw(list all the subroutine names here) {
around $func => sub {
my $orig = shift;
my $self = shift;
warn "Running __PACKAGE__::${func} with:\n";
my $i = 0;
foreach my $param (@_) {
$i++;
# don't display class it$self
next if blessed $param and $param->isa(__PACKAGE__);
if (blessed $param) {
# try not to dump out huge objects
warn "\t$i = $param\n";} else {
warn "\t$i = ".Dumper($param);
}
}
# call the original sub
$self->$orig(@_);
}
}
4) Simple way to log all parameters:
my $r=\@_; $logger->debug('entering ', sub { $logger->dump(args => $r) });
5) Simple way to log method name only, without potentially verbose parameters:
$logger->info("entering ".( caller(0) )[3]);
6) Log4perl configuration
Use %M to log the method name, then just log anything, e.g. "entering".
Labels:
debugging,
moose,
perl,
subroutines,
trace
Subscribe to:
Posts (Atom)