FunctionalPerl

 view release on metacpan or  search on metacpan

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

            map_with_islast
            filter
            TODO_filter_with_tail
            drop_while
            TODO_rtake_while_and_rest
            TODO_rtake_while
            take_while_and_rest
            take_while
            every
            any
            find
            fold
            fold_right
            preferred_fold
            append
            reverse
            take
            drop
            xone
            perhaps_one
            zip
            for_each
            for_each_with_islast
            strings_join
            length
            second
            cons
            array
            list
            stream
            sort
            sortCompare
            group
            string
            values
            ),

        # $class->SUPER::FP_Interface__method_names
    )
}

# XX why sortCompare and not an optional argument to sort ?

#XXX different protocol for random access ones:
#hmm add ref here too?  vs. efficient_ref  etc. *?*  or  slow_ref  or somthing?
#  InefficientSequence
#     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 {

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

        }
    }
}

# This variant folds from whichever side makes more sense for the
# type:
#  *reduce = __PACKAGE__->make_reduce("preferred_fold");

# But, the question is really eager vs. lazy evaluation, i.e. foldl vs
# foldl'. Should we do that? For now just:

sub reduce;
*reduce = __PACKAGE__->make_reduce("fold");

# These variants are explicit in which side they are folding from:

sub reduce_right;
*reduce_right = __PACKAGE__->make_reduce("fold_right");

sub sum {
    @_ == 1 or fp_croak_arity 1;
    $_[0]->reduce(\&add)
}

sub mean {
    @_ == 1 or fp_croak_arity 1;
    my ($s) = @_;

    # XX imprecise for large numbers of items
    $s->sum / $s->length
}

sub median {
    @_ == 1 or fp_croak_arity 1;
    my ($s)    = @_;
    my $sorted = $s->sort(\&real_cmp);
    my $len    = $s->length;
    my $mid    = int($len / 2);
    if (is_even $len) {
        average($sorted->ref($mid - 1), $sorted->ref($mid));
    } else {
        $sorted->ref($mid)
    }
}

sub product {
    @_ == 1 or fp_croak_arity 1;
    $_[0]->reduce(\&mult)
}

sub none {
    @_ == 2 or fp_croak_arity 2;
    my ($s, $pred) = @_;
    $s->every(complement $pred)
}

sub split_at {
    @_ == 2 or fp_croak_arity 2;
    my ($s, $pos) = @_;

    # XXX weaken as all of them.
    ($s->take($pos), $s->drop($pos))
}

sub chunks_of {
    @_ == 2 or fp_croak_arity 2;
    my ($s, $chunklen) = @_;

    # XXX weaken as all of them.
    $s->stream->chunks_of($chunklen)
}

sub strictly_chunks_of {
    @_ == 2 or fp_croak_arity 2;
    my ($s, $chunklen) = @_;

    # XXX weaken as all of them.
    $s->stream->strictly_chunks_of($chunklen)
}

# join in Haskell is doing "++" on the items, should probably choose a
# protocol for this as well; for now, hard-code to strings_join:
sub join {
    my ($s) = @_;

    # Tail-call, please, for 'weakening maintenance'.

    # XX only AUTOLOAD is defined, not `can`! But $s was already
    # forced by the AUTOLOAD thus nothing more is needed here. But
    # this might change!
    my $m = $s->can("strings_join")

        # bug since it's requested by the interface
        or die "bug: missing strings_join method on: $s";

    goto $m
}

# corresponding to is_hashset in FP::HashSet :

sub hashset {
    @_ == 1 or fp_croak_arity 1;
    my ($s) = @_;
    +{ map { $_ => $_ } $s->values }
}

# corresponding to is_uhashset in FP::HashSet :

sub uhashset {
    @_ == 1 or fp_croak_arity 1;
    my ($s) = @_;
    +{ map { $_ => undef } $s->values }
}

_END_



( run in 1.899 second using v1.01-cache-2.11-cpan-39bf76dae61 )