#
# Copyright (c) 2014-2019 Christian Jaeger, copying@christianjaeger.ch
#
# This is free software, offered under either the same terms as perl 5
# or the terms of the Artistic License version 2 or the terms of the
# MIT License (Expat version). See the file COPYING.md that came
# bundled with this file.
#
=head1 NAME
FP::OrderedCollection
=head1 SYNOPSIS
use FP::Equal 'is_equal'; use FP::Stream;
use FP::OrderedCollection;
my $c = FP::OrderedCollection->new_from_values(qw(a b c f));
ok $c->contains("a");
ok not $c->contains("q");
is $c->maybe_position("1"), undef;
is $c->maybe_position("f"), 3;
is_equal [ $c->perhaps_following ("xx")], [];
is_equal $c->perhaps_following("c"), stream('f');
is_equal $c->perhaps_following("b"), stream('c', 'f');
is_equal $c->perhaps_previous("c"), stream('b', 'a');
is $c->maybe_prev("c"), 'b';
is $c->maybe_prev("a"), undef;
is $c->maybe_prev("xx"), undef;
is $c->maybe_next("a"), 'b';
is $c->maybe_next("f"), undef;
=head1 DESCRIPTION
=head1 SEE ALSO
Implements: L<FP::Abstract::Pure>
=head1 NOTE
This is alpha software! Read the status section in the package README
or on the L<website|http://functional-perl.org/>.
=cut
use strict;
use warnings FATAL => 'uninitialized';
qw(subarray_to_stream subarray_to_stream_reverse stream_to_array);
use FP::Struct [[\&is_array, "array"], [\&is_hash, "hash"]],
'FP::Abstract::Pure';
# Unsafe: assumes that the given array is never mutated after
# constructing the OrderedCollection
sub unsafe_new_from_array {
my $cl = shift;
@_ == 1 or fp_croak_arity 1;
my ($a) = @_;
my %h;
for my $i (0 .. $#$a) {
$h{ $$a[$i] } = $i;
}
$cl->new($a, \%h)
}
sub new_from_array {
my $cl = shift;
@_ == 1 or fp_croak_arity 1;
my ($a) = @_;
$cl->unsafe_new_from_array([@$a])
}
sub new_from_values {
my $cl = shift;
$cl->unsafe_new_from_array([@_])
}
sub contains {
my $s = shift;
@_ == 1 or fp_croak_arity 1;
exists $$s{hash}{ $_[0] }
}
sub maybe_position {
my $s = shift;
@_ == 1 or fp_croak_arity 1;
$$s{hash}{ $_[0] }
}
sub perhaps_following {
my $s = shift;
my $i = $s->maybe_position(@_) // return;
subarray_to_stream($$s{array}, $i + 1)
}
sub perhaps_previous {
my $s = shift;
my $i = $s->maybe_position(@_) // return;
subarray_to_stream_reverse($$s{array}, $i - 1)
}
sub maybe_next {
my $s = shift;
my ($l) = $s->perhaps_following(@_) or return undef;
$l = force($l);
is_null($l) ? undef : car $l
}
sub maybe_prev {
my $s = shift;
my ($l) = $s->perhaps_previous(@_) or return undef;
$l = force($l);
is_null($l) ? undef : car $l
}
_END_