Class-Spiffy
view release on metacpan or search on metacpan
lib/Class/Spiffy.pm view on Meta::CPAN
sub_start =>
"sub {\n",
set_default =>
" \$_[0]->{%s} = %s\n unless exists \$_[0]->{%s};\n",
init =>
" return \$_[0]->{%s} = do { my \$self = \$_[0]; %s }\n" .
" unless \$#_ > 0 or defined \$_[0]->{%s};\n",
weak_init =>
" return do {\n" .
" \$_[0]->{%s} = do { my \$self = \$_[0]; %s };\n" .
" Scalar::Util::weaken(\$_[0]->{%s}) if ref \$_[0]->{%s};\n" .
" \$_[0]->{%s};\n" .
" } unless \$#_ > 0 or defined \$_[0]->{%s};\n",
return_if_get =>
" return \$_[0]->{%s} unless \$#_ > 0;\n",
set =>
" \$_[0]->{%s} = \$_[1];\n",
weaken =>
" Scalar::Util::weaken(\$_[0]->{%s}) if ref \$_[0]->{%s};\n",
sub_end =>
" return \$_[0]->{%s};\n}\n",
);
sub field {
my $package = caller;
my ($args, @values) = do {
no warnings;
local *boolean_arguments = sub { (qw(-weak)) };
local *paired_arguments = sub { (qw(-package -init)) };
Class::Spiffy->parse_arguments(@_);
};
my ($field, $default) = @values;
$package = $args->{-package} if defined $args->{-package};
die "Cannot have a default for a weakened field ($field)"
if defined $default && $args->{-weak};
return if defined &{"${package}::$field"};
require Scalar::Util if $args->{-weak};
my $default_string =
( ref($default) eq 'ARRAY' and not @$default )
? '[]'
: (ref($default) eq 'HASH' and not keys %$default )
? '{}'
: default_as_code($default);
my $code = $code{sub_start};
if ($args->{-init}) {
my $fragment = $args->{-weak} ? $code{weak_init} : $code{init};
$code .= sprintf $fragment, $field, $args->{-init}, ($field) x 4;
}
$code .= sprintf $code{set_default}, $field, $default_string, $field
if defined $default;
$code .= sprintf $code{return_if_get}, $field;
$code .= sprintf $code{set}, $field;
$code .= sprintf $code{weaken}, $field, $field
if $args->{-weak};
$code .= sprintf $code{sub_end}, $field;
my $sub = eval $code;
die $@ if $@;
no strict 'refs';
*{"${package}::$field"} = $sub;
return $code if defined wantarray;
}
use lib 't', 'lib';
use strict;
use warnings;
package Foo;
use Class::Spiffy -base;
my $test1 = field test1 => [];
my $test2 = field test2 => {};
my $test3 = field test3 => [1..4];
my $test4 = field test4 => {1..4};
my $test5 = field test5 => -weaken;
my $test6 = field test6 => -init => '$self->setup(@_)';
my $test7 = field test7 => -weak => -init => '$self->setup(@_)';
package main;
use Test::More tests => 7;
my @expected = map { s/\r//g; $_ } split /\.\.\.\r?\n/, join '', <DATA>;
my $i = 1;
for my $expected (@expected) {
'3' => 4
}
unless exists $_[0]->{test4};
return $_[0]->{test4} unless $#_ > 0;
$_[0]->{test4} = $_[1];
return $_[0]->{test4};
}
...
sub {
$_[0]->{test5} = '-weaken'
unless exists $_[0]->{test5};
return $_[0]->{test5} unless $#_ > 0;
$_[0]->{test5} = $_[1];
return $_[0]->{test5};
}
...
sub {
return $_[0]->{test6} = do { my $self = $_[0]; $self->setup(@_) }
unless $#_ > 0 or defined $_[0]->{test6};
return $_[0]->{test6} unless $#_ > 0;
$_[0]->{test6} = $_[1];
return $_[0]->{test6};
}
...
sub {
return do {
$_[0]->{test7} = do { my $self = $_[0]; $self->setup(@_) };
Scalar::Util::weaken($_[0]->{test7}) if ref $_[0]->{test7};
$_[0]->{test7};
} unless $#_ > 0 or defined $_[0]->{test7};
return $_[0]->{test7} unless $#_ > 0;
$_[0]->{test7} = $_[1];
Scalar::Util::weaken($_[0]->{test7}) if ref $_[0]->{test7};
return $_[0]->{test7};
}
( run in 0.372 second using v1.01-cache-2.11-cpan-a9ef4e587e4 )