package Set; use Moo; has 'items' => (is => 'ro', default => sub { [ ] }); no Moo; sub has { my ($self, $e) = @_; scalar grep { $_ == $e } @{ $self->items }; } sub add { my ($self, $e) = @_; if ( ! $self->has($e) ) { push @{ $self->items }, $e; } } 1; #### % reply 0> use Set 1> my $s = Set->new $res[0] = bless( { 'items' => [] }, 'Set' ) 2> $s->has(42) $res[1] = 0 3> $s->add(42) $res[2] = 1 4> $s->has(42) $res[3] = 1 #### package BobUtil; use strict; use List::Util qw(min max); sub set_min { my ($set) = @_; min @{ $set->items }; } sub set_max { my ($set) = @_; max @{ $set->items }; } 1; #### % reply 0> use Set 1> use BobUtil 2> my $s = Set->new $res[0] = bless( { 'items' => [] }, 'Set' ) 3> $s->add($_) for 1 .. 5 $res[1] = '' 4> BobUtil::set_min($s) $res[2] = 1 5> BobUtil::set_max($s) $res[3] = 5 #### package BobSet; use Moo; use List::Util qw(min max); extends 'Set'; no Moo; sub numeric_min { my ($self) = @_; min @{ $self->items }; } sub numeric_max { my ($self) = @_; max @{ $self->items }; } 1; #### % reply 0> use BobSet 1> my $s = BobSet->new $res[0] = bless( { 'items' => [] }, 'BobSet' ) 2> $s->add($_) for 1 .. 5 $res[1] = '' 3> $s->numeric_min $res[2] = 1 4> $s->numeric_max $res[3] = 5 #### package Set; use Moo; has 'items' => (is => 'ro', default => sub { { } }); no Moo; sub has { my ($self, $e) = @_; exists $self->items->{ $e }; } sub add { my ($self, $e) = @_; if ( ! $self->has($e) ) { $self->items->{ $e } = 1; } } 1; #### % reply 0> use BobSet 1> my $s = BobSet->new $res[0] = bless( { 'items' => {} }, 'BobSet' ) 2> $s->add($_) for 1 .. 5 $res[1] = '' 3> $s->numeric_min Not an ARRAY reference at BobSet.pm line 11. #### % reply 0> use Set 1> use BobUtil 2> my $s = Set->new $res[0] = bless( { 'items' => {} }, 'Set' ) 3> $s->add($_) for 1 .. 5 $res[1] = '' 4> BobUtil::set_min($s) Not an ARRAY reference at BobUtil.pm line 8. #### package Set; use Moo; has '_items' => (is => 'ro', default => sub { { } }); no Moo; sub items { my ($self) = @_; [ keys %{ $self->_items } ]; } sub has { my ($self, $e) = @_; exists $self->_items->{ $e }; } sub add { my ($self, $e) = @_; if ( ! $self->has($e) ) { $self->_items->{ $e } = 1; } } 1; #### % reply 0> use BobSet 1> my $s = BobSet->new $res[0] = bless( { '_items' => {} }, 'BobSet' ) 2> $s->add($_) for 1 .. 5 $res[1] = '' 3> $s->numeric_min $res[2] = '1' 4> $s->numeric_max $res[3] = '5' #### % reply 0> use Set 1> my $s = Set->new(_items => [1 .. 4]) $res[0] = bless( { '_items' => [ 1, 2, 3, 4 ] }, 'Set' ) 2> $s->add(5) Not a HASH reference at Set.pm line 15. #### package Set; use Moo; has '_items' => (is => 'ro', default => sub { { } }); no Moo; sub BUILDARGS { shift; return { _items => { map { $_ => 1 } @_ } }; } sub items { my ($self) = @_; [ keys %{ $self->_items } ]; } sub has { my ($self, $e) = @_; exists $self->_items->{ $e }; } sub add { my ($self, $e) = @_; if ( ! $self->has($e) ) { $self->_items->{ $e } = 1; } } 1; #### % reply 0> use Set 1> my $s = Set->new(1 .. 4) $res[0] = bless( { '_items' => { '1' => 1, '2' => 1, '3' => 1, '4' => 1 } }, 'Set' ) 2> $s->has(5) $res[1] = '' 3> $s->has(3) $res[2] = 1 #### % reply 0> use RememberingSet 1> $s = RememberingSet->new 3> $s->has(1) $res[1] = '' 4> $s->add(1) $res[2] = 1 5> $s->seen(1) $res[3] = 2 6> $s->seen(2) $res[4] = 0 #### package RememberingSet; use Moo; has '_count' => (is => 'ro', default => sub { { } }); extends 'Set'; no Moo; sub has { my ($self, $e) = @_; $self->_count->{ $e }++; $self->SUPER::has($e); } sub add { my ($self, $e) = @_; $self->_count->{ $e }++; $self->SUPER::add($e); } sub seen { my ($self, $e) = @_; exists $self->_count->{ $e } ? $self->_count->{ $e } : 0; } 1; #### % reply 0> use RememberingSet 1> my $s = RememberingSet->new $res[0] = bless( { '_count' => {}, '_items' => {} }, 'RememberingSet' ) 2> $s->has(1) $res[1] = '' 3> $s->add(1) $res[2] = 1 4> $s->seen(1) $res[3] = 3 #### package RememberingSet; use Moo; use Set; has '_count' => (is => 'ro', default => sub { { } }); has '_set' => (is => 'ro', default => sub { Set->new }); no Moo; sub has { my ($self, $e) = @_; $self->_count->{ $e }++; $self->_set->has($e); } sub add { my ($self, $e) = @_; $self->_count->{ $e }++; $self->_set->add($e); } sub seen { my ($self, $e) = @_; exists $self->_count->{ $e } ? $self->_count->{ $e } : 0; } 1; #### package RememberingSet; use Moo; use Set; my $Delegated = [qw/add has/]; has '_count' => (is => 'ro', default => sub { { } }); has '_set' => (is => 'ro', default => sub { Set->new }, handles => $Delegated); around $Delegated => sub { my ($orig, $self, $e) = @_; $self->_count->{ $e }++; $self->$orig($e); }; no Moo; sub seen { my ($self, $e) = @_; exists $self->_count->{ $e } ? $self->_count->{ $e } : 0; } 1;