Acme-Sort-Sleep
view release on metacpan or search on metacpan
local/lib/perl5/Struct/Dumb.pm view on Meta::CPAN
}
if( my ( $extrakey ) = keys %values ) {
croak "usage: $pkg does not recognise '$extrakey'";
}
bless \@values, $pkg;
};
}
else {
my $fieldcount = @$fields;
my $argnames = join ", ", map "\$$_", @$fields;
$constructor = sub {
@_ == $fieldcount or croak "usage: $pkg($argnames)";
bless [ @_ ], $pkg;
};
}
no strict 'refs';
*{"${pkg}::$_"} = $subs{$_} for keys %subs;
*{"${caller}::$name"} = $constructor;
if( my $predicate = $opts{predicate} ) {
*{"${caller}::$predicate"} = sub { ( ref($_[0]) || "" ) eq $pkg };
}
*{"${pkg}::_forbid_arrayification"} = sub {
return if !HAVE_OVERLOADING and caller eq __PACKAGE__;
croak "Cannot use $pkg as an ARRAY reference"
};
require overload;
$pkg->overload::OVERLOAD(
'@{}' => sub { $_[0]->_forbid_arrayification; return $_[0] },
'0+' => sub { refaddr $_[0] },
'""' => sub { sprintf "%s=Struct::Dumb(%#x)", $pkg, refaddr $_[0] },
'bool' => sub { 1 },
fallback => 1,
);
}
=head2 struct
struct $name => [ @fieldnames ],
named_constructor => (1|0),
predicate => "is_$name";
Creates a new structure type. This exports a new function of the type's name
into the caller's namespace. Invoking this function returns a new instance of
a type that implements those field names, as accessors and mutators for the
fields.
Takes the following options:
=over 4
=item named_constructor => BOOL
Determines whether the structure will take positional or named arguments.
=item predicate => STR
If defined, gives the name of a second function to export to the caller's
namespace. This function will be a type test predicate; that is, a function
that takes a single argmuent, and returns true if-and-only-if that argument is
an instance of this structure type.
=back
=cut
=head2 readonly_struct
readonly_struct $name => [ @fieldnames ],
...
Similar to L</struct>, but instances of this type are immutable once
constructed. The field accessor methods will not be marked with the
C<:lvalue> attribute.
Takes the same options as L</struct>.
=cut
=head1 NOTES
=head2 Allowing ARRAY dereference
The way that forbidding access to instances as if they were ARRAY references
is currently implemented uses an internal method on the generated structure
class called C<_forbid_arrayification>. If special circumstances require that
this exception mechanism be bypassed, the method can be overloaded with an
empty C<sub {}> body, allowing the struct instances in that class to be
accessed like normal ARRAY references. For good practice this should be
limited by a C<local> override.
For example, L<Devel::Cycle> needs to access the instances as plain ARRAY
references so it can walk the data structure looking for reference cycles.
use Devel::Cycle;
{
no warnings 'redefine';
local *Point::_forbid_arrayification = sub {};
memory_cycle_ok( $point );
}
=head1 TODO
=over 4
=item *
Consider adding an C<coerce_hash> option, giving name of another function to
convert structs to key/value pairs, or a HASH ref.
=back
=head1 AUTHOR
Paul Evans <leonerd@leonerd.org.uk>
( run in 1.121 second using v1.01-cache-2.11-cpan-39bf76dae61 )