Last active
January 4, 2016 15:09
-
-
Save peczenyj/8639328 to your computer and use it in GitHub Desktop.
My example of frequency iterator.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| use strict; | |
| use warnings; | |
| package Java::Util::Iterator; | |
| use Moose::Role; | |
| requires 'hasNext', 'next', 'remove'; | |
| package Frequency::Iterator::Single; | |
| use Carp qw(croak); | |
| use Moose; | |
| with 'Java::Util::Iterator'; | |
| has 'value' => ( | |
| is => 'ro', | |
| required => 1, | |
| ); | |
| has 'frequency' => ( | |
| is => 'ro', | |
| isa => 'Num', | |
| traits => ['Counter'], | |
| required => 1, | |
| handles => { | |
| decrease_frequency => 'dec' | |
| } | |
| ); | |
| sub hasNext { | |
| my $self = shift; | |
| $self->frequency > 0 | |
| } | |
| sub next { | |
| my $self = shift; | |
| croak 'NoSuchElementException' unless $self->hasNext; | |
| $self->decrease_frequency; | |
| $self->value | |
| } | |
| sub remove { 1 } | |
| package Frequency::Iterator::Multiple; | |
| use Carp qw(croak); | |
| use List::MoreUtils qw(pairwise); | |
| use Moose; | |
| with 'Java::Util::Iterator'; | |
| has '_fv_iterators' => ( | |
| is => 'ro', | |
| isa => 'ArrayRef[Java::Util::Iterator]', | |
| required => 1, | |
| traits => ['Array'], | |
| handles => { | |
| _go_to_next_iterator => 'shift', | |
| _has_next_iterator => 'count', | |
| } | |
| ); | |
| sub hasNext { | |
| my ($self) = @_; | |
| $self->_has_next_iterator && $self->_last->hasNext; | |
| } | |
| sub next { | |
| my ($self) = @_; | |
| croak 'NoSuchElementException' unless $self->hasNext; | |
| $self->_go_to_next_iterator while (! $self->_first->hasNext); | |
| $self->_first->next; | |
| } | |
| sub remove { 1 } | |
| # private methods | |
| sub _first { | |
| my ($self) = @_; | |
| $self->_fv_iterators->[0] | |
| } | |
| sub _last { | |
| my ($self) = @_; | |
| $self->_fv_iterators->[-1] | |
| } | |
| package Frequency::Iterator; | |
| use Carp qw(croak); | |
| use List::MoreUtils qw(pairwise); | |
| #builder method | |
| sub build { | |
| my ($klass, $frequencies, $values) = @_; | |
| croak "ops, size of (frequencies) and (value) should be equal" | |
| unless scalar(@$frequencies) == scalar(@$values); | |
| my @fv = map { | |
| Frequency::Iterator::Single->new( | |
| frequency => $_->[0], | |
| value => $_->[1], | |
| ); | |
| } grep { | |
| $_->[0] > 0 | |
| } pairwise { | |
| our($a, $b); | |
| [ $a, $b ] | |
| } @$frequencies, @$values; | |
| return Frequency::Iterator::Multiple->new( _fv_iterators => \@fv ); | |
| } | |
| package main; | |
| use Test::More; | |
| use Test::Exception; | |
| subtest "should create one instance of java.util.iterator" => sub { | |
| my $freq_it = Frequency::Iterator->build( | |
| [1,2] => [4,5], | |
| ); | |
| ok $freq_it->DOES('Java::Util::Iterator'); | |
| }; | |
| subtest "normal" => sub { | |
| my $freq_it = Frequency::Iterator->build( | |
| [1,2] => [4,5], | |
| ); | |
| ok($freq_it->hasNext, 'should has next'); | |
| is($freq_it->next, 4, 'should return 4'); | |
| ok($freq_it->hasNext, 'should has next'); | |
| is($freq_it->next, 5, 'should return 5'); | |
| ok($freq_it->hasNext, 'should has next'); | |
| is($freq_it->next, 5, 'should return 5 again'); | |
| ok(! $freq_it->hasNext, 'should return false (end)'); | |
| }; | |
| subtest "normal with zero" => sub { | |
| my $freq_it = Frequency::Iterator->build( | |
| [1,0,2] => [4,9,5], | |
| ); | |
| ok($freq_it->hasNext, 'should has next'); | |
| is($freq_it->next, 4, 'should return 4'); | |
| ok($freq_it->hasNext, 'should has next'); | |
| is($freq_it->next, 5, 'should return 5'); | |
| ok($freq_it->hasNext, 'should has next'); | |
| is($freq_it->next, 5, 'should return 5 again'); | |
| ok(! $freq_it->hasNext, 'should return false (end)'); | |
| }; | |
| subtest "normal with zero 2" => sub { | |
| my $freq_it = Frequency::Iterator->build( | |
| [1,0,2,0] => [4,9,5,1], | |
| ); | |
| ok($freq_it->hasNext, 'should has next'); | |
| is($freq_it->next, 4, 'should return 4'); | |
| ok($freq_it->hasNext, 'should has next'); | |
| is($freq_it->next, 5, 'should return 5'); | |
| ok($freq_it->hasNext, 'should has next'); | |
| is($freq_it->next, 5, 'should return 5 again'); | |
| ok(! $freq_it->hasNext, 'should return false (end)'); | |
| }; | |
| subtest "normal with zero 3" => sub { | |
| my $freq_it = Frequency::Iterator->build( | |
| [1,0,0,2,0] => [4,9,7,5,1], | |
| ); | |
| ok($freq_it->hasNext, 'should has next'); | |
| is($freq_it->next, 4, 'should return 4'); | |
| ok($freq_it->hasNext, 'should has next'); | |
| is($freq_it->next, 5, 'should return 5'); | |
| ok($freq_it->hasNext, 'should has next'); | |
| is($freq_it->next, 5, 'should return 5 again'); | |
| ok(! $freq_it->hasNext, 'should return false (end)'); | |
| }; | |
| subtest "should die if call next and there is nothing" => sub { | |
| my $freq_it = Frequency::Iterator->build( | |
| [1] => [1] | |
| ); | |
| ok($freq_it->hasNext, 'should has next'); | |
| is($freq_it->next, 1, 'should return 1'); | |
| ok(! $freq_it->hasNext, 'should return false (end)'); | |
| throws_ok { | |
| $freq_it->next | |
| } | |
| qr/NoSuchElementException/, | |
| 'should die with NoSuchElementException'; | |
| }; | |
| subtest "should die if call next and there is nothing" => sub { | |
| my $freq_it = Frequency::Iterator->build( | |
| [] => [] | |
| ); | |
| ok(! $freq_it->hasNext, 'should return false (end)'); | |
| throws_ok { | |
| $freq_it->next | |
| } | |
| qr/NoSuchElementException/, | |
| 'should die with NoSuchElementException'; | |
| }; | |
| done_testing; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| $ prove -v freq_it.pl | |
| freq_it.pl .. | |
| ok 1 | |
| 1..1 | |
| ok 1 - should create one instance of java.util.iterator | |
| ok 1 - should has next | |
| ok 2 - should return 4 | |
| ok 3 - should has next | |
| ok 4 - should return 5 | |
| ok 5 - should has next | |
| ok 6 - should return 5 again | |
| ok 7 - should return false (end) | |
| 1..7 | |
| ok 2 - normal | |
| ok 1 - should has next | |
| ok 2 - should return 4 | |
| ok 3 - should has next | |
| ok 4 - should return 5 | |
| ok 5 - should has next | |
| ok 6 - should return 5 again | |
| ok 7 - should return false (end) | |
| 1..7 | |
| ok 3 - normal with zero | |
| ok 1 - should has next | |
| ok 2 - should return 4 | |
| ok 3 - should has next | |
| ok 4 - should return 5 | |
| ok 5 - should has next | |
| ok 6 - should return 5 again | |
| ok 7 - should return false (end) | |
| 1..7 | |
| ok 4 - normal with zero 2 | |
| ok 1 - should has next | |
| ok 2 - should return 4 | |
| ok 3 - should has next | |
| ok 4 - should return 5 | |
| ok 5 - should has next | |
| ok 6 - should return 5 again | |
| ok 7 - should return false (end) | |
| 1..7 | |
| ok 5 - normal with zero 3 | |
| ok 1 - should has next | |
| ok 2 - should return 1 | |
| ok 3 - should return false (end) | |
| ok 4 - should die with NoSuchElementException | |
| 1..4 | |
| ok 6 - should die if call next and there is nothing | |
| ok 1 - should return false (end) | |
| ok 2 - should die with NoSuchElementException | |
| 1..2 | |
| ok 7 - should die if call next and there is nothing | |
| 1..7 | |
| ok | |
| All tests successful. | |
| Files=1, Tests=7, 1 wallclock secs ( 0.02 usr 0.00 sys + 0.18 cusr 0.01 csys = 0.21 CPU) | |
| Result: PASS |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment