Skip to content

Instantly share code, notes, and snippets.

@peczenyj
Last active January 4, 2016 15:09
Show Gist options
  • Select an option

  • Save peczenyj/8639328 to your computer and use it in GitHub Desktop.

Select an option

Save peczenyj/8639328 to your computer and use it in GitHub Desktop.
My example of frequency iterator.
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;
$ 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