FunctionalPerl

 view release on metacpan or  search on metacpan

lib/FP/Abstract/Sequence.pm  view on Meta::CPAN

#     ref
# last
# butlast
#  also  sub  subsection  slice ?
# *set = blessing \&array_set;
# *push = blessing \&array_push;
# *pop = blessing_snd \&array_pop;
# *shift = blessing_snd \&array_shift;
# *unshift = blessing \&array_unshift;

#XXX other
# group group_by
#     zip2

# XXX these don't weaken the caller arguments, thus will leak for
# streams. How to solve this (and not copy-paste-adapt the methods
# manually) without fixing perl?

sub flatten {
    @_ == 1 or @_ == 2 or fp_croak_arity "1 or 2";
    my ($self, $perhaps_tail) = @_;
    $self->fold_right(
        sub {
            my ($v, $rest) = @_;
            $v->append($rest)
        },
        @_ == 2 ? $perhaps_tail : FP::List::null()
    );
}

# XXX and on top of that, these return a lazy result even if the input
# isn't; related to the above issue. Find solution for both.

# (XX only works computationally efficient for *some* sequences;
# introduce an FP::Abstract::IterativeSequence or so and move it
# there?)
sub intersperse {
    @_ == 2 or fp_croak_arity 2;
    my ($self, $value) = @_;

    # (should we recurse locally like most sequence functions? Or is
    # it actually a good idea to call the method on the rest (for
    # improper_listS, but once we introduce a `cons` method on
    # PureArray etc. that won't happen anymore?)?)
    lazy {
        $self->is_null ? $self : do {
            my ($v, $rest) = $self->first_and_rest;
            $rest->is_null
                ? $self
                : FP::List::cons($v,
                FP::List::cons($value, $rest->intersperse($value)))
        }
    }
}

# XX better name?
sub extreme {
    @_ == 2 or fp_croak_arity 2;
    my ($self, $cmp) = @_;

    # XXX: fold_right is good for FP::Stream streaming. left fold will
    # be better for FP::List. How? Add fold_left for explicit left
    # folding and make fold chose the preferred solution for
    # order-irrelevant folding?
    $self->rest->fold(
        sub {
            my ($v, $res) = @_;
            my $c = &$cmp($v, $res);
            $c < 0 ? $v : $res
        },
        $self->first
    );
}

sub min {
    @_ == 1 or @_ == 2 or fp_croak_arity "1 or 2";
    my ($self, $maybe_cmp) = @_;
    $self->extreme($maybe_cmp // sub { $_[0] <=> $_[1] })
}

sub max {
    @_ == 1 or @_ == 2 or fp_croak_arity "1 or 2";
    my ($self, $maybe_cmp) = @_;
    $self->extreme(
        defined($maybe_cmp)
        ? cmp_complement($maybe_cmp)
        : sub { -($_[0] <=> $_[1]) })
}

sub minmax {
    @_ == 1 or @_ == 2 or fp_croak_arity "1 or 2";
    my ($self, $maybe_extract) = @_;

    # XXX same comment as in `extreme`
    @{
        $self->rest->fold(
            defined $maybe_extract
            ? sub {
                my ($v,   $res) = @_;
                my ($min, $max) = @$res;
                my $v_ = &$maybe_extract($v);
                [
                    $v_ < &$maybe_extract($min) ? $v : $min,
                    $v_ > &$maybe_extract($max) ? $v : $max
                ]
            }
            : sub {
                my ($v,   $res) = @_;
                my ($min, $max) = @$res;
                [$v < $min ? $v : $min, $v > $max ? $v : $max]
            },
            [$self->first, $self->first]
        )
    }
}

sub subsection {
    @_ == 3 or fp_croak_arity 3;
    my ($self, $i0, $i1) = @_;

    # XXX same comment as in `extreme`



( run in 0.738 second using v1.01-cache-2.11-cpan-140bd7fdf52 )