# # 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::Array::Mixin =head1 SYNOPSIS =head1 DESCRIPTION Used to implement array based sequences. =head1 SEE ALSO L, L L -- definition of most functions used here =head1 NOTE This is alpha software! Read the package README. =cut package FP::Array::Mixin; use strict; use warnings; use warnings FATAL => 'uninitialized'; use FP::Optional qw(perhaps_to_maybe); use FP::Combinators qw (flip flip2of3 rot3right rot3left); use FP::Array ":all"; use FP::Array_sort "array_sort"; sub blessing ($) { my ($m)= @_; sub { my $class=ref $_[0]; if (my ($v)= &$m (@_)) { $class->new_from_array($v) } else { () } } } sub blessing_snd ($) { my ($m)= @_; sub { my $class=ref $_[0]; wantarray ? do { my ($v,$a)= &$m (@_); ($v, $class->new_from_array($a)) } : $class->new_from_array((&$m (@_))[-1]); } } use Chj::NamespaceCleanAbove; sub FP_Show_show { my ($s,$show)=@_; $s->constructor_name."(".join(", ", @{array_map($show,$s)}).")" } *FP_Equal_equal= *array_equal; # de-import array from FP::Array to avoid redefinition warning BEGIN {undef *array } sub array { @_==1 or die "wrong number of arguments"; my $s=shift; # 'debless', and copy necessary as the user is entitled to mod it # now. (XX: might optimize if only reference left by checking the # refcount) [@$s] } sub list { @_==1 or die "wrong number of arguments"; my $s=shift; require FP::List; # (overhead of repeated require?) FP::List::array_to_list ($s) } sub stream { @_==1 or die "wrong number of arguments"; my $s=shift; require FP::Stream; # (ditto) FP::Stream::array_to_stream ($s) } sub is_null { @_==1 or die "wrong number of arguments"; not @{$_[0]} } # Do *not* provide `is_pair`, though, since this is not a pair based # data structure? Or is the `is_null` already evil because of this and # should be named `is_empty`? sub values { @{$_[0]} } *cons= flip \&FP::List::pair; # XX ? Also, XXX FP::List might not # be loaded here *first= \&array_first; *maybe_first= \&array_maybe_first; *perhaps_first= \&array_perhaps_first; *rest= blessing \&array_rest; *maybe_rest= blessing \&array_maybe_rest; *perhaps_rest= blessing \&array_perhaps_rest; sub first_and_rest { @_==1 or die "wrong number of arguments"; my ($a)= @_; (array_first $a, ref($a)->new_from_array(array_rest($a))) } # XXX ah could have used blessing_snd ^ v sub maybe_first_and_rest { @_==1 or die "wrong number of arguments"; my ($a)= @_; @$a ? (array_first $a, ref($a)->new_from_array(array_rest($a))) : undef } sub perhaps_first_and_rest { @_==1 or die "wrong number of arguments"; my ($a)= @_; @$a ? (array_first $a, ref($a)->new_from_array(array_rest($a))) : () } *second= \&array_second; *last= \&array_last; *ref= \&array_ref; *FP_Sequence_ref=*ref; *length= \&array_length; sub FP_Sequence_length { my ($self,$prefixlen)=@_; $prefixlen + $self->length } *set= blessing \&array_set; *update= blessing \&array_update; *push= blessing \&array_push; *pop= blessing_snd \&array_pop; *shift= blessing_snd \&array_shift; *unshift= blessing \&array_unshift; *sub= blessing \&array_sub; *take= blessing \&array_take; *drop= blessing \&array_drop; *drop_while= blessing \&array_drop_while; *take_while= blessing \&array_take_while; *append= blessing \&array_append; *reverse= blessing \&array_reverse; *xone= \&array_xone; *perhaps_one= \&array_perhaps_one; *hashing_uniq= blessing \&array_hashing_uniq; *zip2= blessing \&array_zip2; *for_each= flip \&array_for_each; *map= blessing flip \&array_map; *map_with_i= blessing flip \&array_map_with_i; *map_with_islast= blessing flip \&array_map_with_islast; *filter= blessing flip \&array_filter; *zip= blessing \&array_zip; *fold= rot3left \&array_fold; *fold_right= rot3left \&array_fold_right; *preferred_fold= *fold; # ? *join= blessing \&array_join; *strings_join= \&array_strings_join; *every= flip \&array_every; *any= flip \&array_any; *sum= \&array_sum; *hash_group_by= \&array_to_hash_group_by; *sort= blessing \&array_sort; # XX provide them as functions, too? (prefixed with `purearray_`) (to # avoid requiring the user to use `the_method` [and perhaps missing # the explicit type check?]) *perhaps_find_tail= blessing flip \&array_perhaps_find_tail; *perhaps_find= flip \&array_perhaps_find; *find= perhaps_to_maybe (\&array_perhaps_find); _END_ # Chj::NamespaceCleanAbove