[m-rev.] for review: Add take_while and drop_while to the list module
Peter Wang
novalazy at gmail.com
Thu Apr 21 23:09:25 AEST 2016
On Thu, 21 Apr 2016 17:09:07 +1000, Paul Bone <paul at bone.id.au> wrote:
>
> Here's the updated diff. I've fixed the doc comment for drop_while, renamed
> take_while/4 to split_while/4, and moved it and the deprecated takewhile/4
> so that they're after the other split predicates but before the take
> predicates. I think this a better name than take_while, and a
> re-arrangement to put predicates near to other relevant ones.
Hi Paul,
I disagree. take_while is the better name. Repeatedly "take" the head
of the list "while" this condition is true, and optionally return the
rest.
In split_list/split_upto, "split" means to split a list into a prefix
and suffix. "split_while" suggests repeatedly splitting a list into a
prefix and suffix (not necessarily head and tail). It's unclear what
that operation would be.
> diff --git a/NEWS b/NEWS
> index c269b21..313e4a9 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -280,6 +280,14 @@ Changes to the Mercury standard library:
>
> - reverse_prepend/2
> - reverse_prepend/3
> + - take_while/3
> + - take_while/2
> + - drop_while/3
> + - drop_while/2
> + - split_while/4
> +
> +* The dropwhile/4 predicate has been deprecated in the list module,
> + split_while/4 can be used instead.
takewhile/4
> diff --git a/library/list.m b/library/list.m
> index 9565434..a90f95b 100644
> --- a/library/list.m
> +++ b/library/list.m
> @@ -230,6 +230,22 @@
> :- pred split_upto(int::in, list(T)::in, list(T)::out, list(T)::out)
> is det.
>
> + % split_while(Predicate, List, UptoList, AfterList) takes a
> + % closure with one input argument, and calls it on successive members
> + % of List as long as the calls succeed. The elements for which
> + % the call succeeds are placed in UptoList and the first element for
> + % which the call fails, and all the remaining elements of List are
> + % placed in AfterList.
> + %
> +:- pred split_while(pred(T)::in(pred(in) is semidet), list(T)::in,
> + list(T)::out, list(T)::out) is det.
I see that's the old description but it's very operational.
The order of UptoList is unconstrained. It could be clearer
about the AfterList = [] case.
Here's another attempt:
take_while(Pred, List, Start, End):
List = Start ++ End. Start is the longest prefix of List
where Pred succeeds for every element in Start.
End is the remainder of the list.
> + % takewhile/4 is the old name for split_while/4.
> + %
> +:- pragma obsolete(takewhile/4).
> +:- pred takewhile(pred(T)::in(pred(in) is semidet), list(T)::in,
> + list(T)::out, list(T)::out) is det.
> +
> % take(Len, List, Start):
> %
> % `Start' is the first `Len' elements of `List'. Fails if `List' has
> @@ -251,6 +267,15 @@
> :- pred take_upto(int::in, list(T)::in, list(T)::out) is det.
> :- func take_upto(int, list(T)) = list(T).
>
> + % take_while(Pred, List, Start):
> + %
> + % 'Start' is the first elements of 'List' that satisfy 'Pred'.
> + %
take_while(Pred, List, Start) :-
take_while(Pred, List, Start, _End).
or from above: Start is the longest prefix ...
> +:- pred take_while(pred(T)::in(pred(in) is semidet), list(T)::in,
> + list(T)::out) is det.
> +:- func take_while(pred(T), list(T)) = list(T).
> +:- mode take_while(pred(in) is semidet, in) = out is det.
> +
> % drop(Len, List, End):
> %
> % `End' is the remainder of `List' after removing the first `Len' elements.
> @@ -267,6 +292,16 @@
> %
> :- pred det_drop(int::in, list(T)::in, list(T)::out) is det.
>
> + % drop_while(Pred, List, End):
> + %
> + % Drop items that satisfy 'Pred' from the head of 'List' leaving only
> + % 'End'.
> + %
drop_while(Pred, List, End) :-
take_while(Pred, List, _Start, End).
or
End is the remainder of List after removing all the consecutive
elements from the start of List for which Pred succeeds.
Peter
More information about the reviews
mailing list