[m-rev.] diff: add a test case for list.split_upto/4 and list.take_upto/3
Julien Fischer
jfischer at opturion.com
Thu Jun 9 11:30:47 AEST 2016
On Thu, 9 Jun 2016, Mark Brown wrote:
> On Wed, Jun 8, 2016 at 4:21 PM, Julien Fischer <jfischer at opturion.com> wrote:
>> I am inclined to change the behaviour of both of these predicates so
>> that they throw an exception if their first argument is negative.
>> Opinions?
>
> I agree with this change.
Here's a diff that making that change.
Julien.
----------------------
Make list.split_upto and list.take_upto abort for N < 0.
library/list.m:
Make split_upto/4 and take_upto/{2,3} abort for N < 0.
tests/hard_coded/take_split_upto.{m,exp}:
Update this test case to test the for new behaviour.
tests/hard_coded/Mmakefile:
Do not run the take_split_upto test case in deep profiling
grades since it now requires catching exceptions to be supported.
NEWS:
Announce the above change.
diff --git a/NEWS b/NEWS
index 42ac2da..5147773 100644
--- a/NEWS
+++ b/NEWS
@@ -312,6 +312,10 @@ Changes to the Mercury standard library:
* The take/3 and drop/3 predicates in the list module have been modified
so that they fail if their first argument is less than zero.
+* The split_upto/4 and take_upto/3 predicates and take_upto/2 function
+ in the list module have been modified so that they throw an exception
+ if their first argument is negative.
+
* The following predicate and function in the builtin module have been
deprecated and will be removed in a future release:
diff --git a/library/list.m b/library/list.m
index bf567b8..60e0a36 100644
--- a/library/list.m
+++ b/library/list.m
@@ -226,7 +226,8 @@
% split_upto(N, List, Start, End):
%
% splits `List' into a prefix `Start' of length `min(N, length(List))',
- % and a remainder `End'. See also: split_list, take, drop.
+ % and a remainder `End'. Throws an exception if `N' < 0.
+ % See also: split_list, take, drop.
%
:- pred split_upto(int::in, list(T)::in, list(T)::out, list(T)::out)
is det.
@@ -247,7 +248,7 @@
% take_upto(Len, List, Start):
%
% `Start' is the first `Len' elements of `List'. If `List' has less than
- % `Len' elements, return the entire list.
+ % `Len' elements, return the entire list. Throws an exception if `N' < 0.
%
:- pred take_upto(int::in, list(T)::in, list(T)::out) is det.
:- func take_upto(int, list(T)) = list(T).
@@ -2326,12 +2327,23 @@ det_split_list(N, List, Start, End) :-
unexpected($module, $pred, "index out of range")
).
+
split_upto(N, List, Start, End) :-
+ ( if N < 0 then
+ unexpected($file, $pred, "index is negative")
+ else
+ do_split_upto(N, List, Start, End)
+ ).
+
+:- pred do_split_upto(int::in, list(T)::in, list(T)::out, list(T)::out)
+ is det.
+
+do_split_upto(N, List, Start, End) :-
( if
N > 0,
List = [Head | Tail]
then
- split_upto(N - 1, Tail, StartTail, End),
+ do_split_upto(N - 1, Tail, StartTail, End),
Start = [Head | StartTail]
else
Start = [],
@@ -2361,6 +2373,15 @@ take_upto(N, Xs) = InitialXs :-
list.take_upto(N, Xs, InitialXs).
take_upto(N, Xs, InitialXs) :-
+ ( if N < 0 then
+ unexpected($file, $pred, "index is negative")
+ else
+ do_take_upto(N, Xs, InitialXs)
+ ).
+
+:- pred do_take_upto(int::in, list(T)::in, list(T)::out) is det.
+
+do_take_upto(N, Xs, InitialXs) :-
( if list.take(N, Xs, InitialXsPrime) then
InitialXs = InitialXsPrime
else
diff --git a/tests/hard_coded/Mmakefile b/tests/hard_coded/Mmakefile
index 2d36bb4..d6cc299 100644
--- a/tests/hard_coded/Mmakefile
+++ b/tests/hard_coded/Mmakefile
@@ -312,7 +312,6 @@ ORDINARY_PROGS = \
switch_detect \
system_sort \
tag_switch_dup_label \
- take_split_upto \
term_io_test \
term_to_univ_test \
test234_sorted_insert \
@@ -620,6 +619,7 @@ ifeq "$(findstring profdeep,$(GRADE))" ""
map_merge_test \
mutable_excp \
null_char \
+ take_split_upto \
test_array2d \
test_injection \
try_syntax_1 \
diff --git a/tests/hard_coded/take_split_upto.exp b/tests/hard_coded/take_split_upto.exp
index 10d15c0..f11804b 100644
--- a/tests/hard_coded/take_split_upto.exp
+++ b/tests/hard_coded/take_split_upto.exp
@@ -1,9 +1,9 @@
-take_upto(int.min_int, []) ===> []
-take_upto(int.min_int, [111]) ===> [111]
-take_upto(int.min_int, [111, 222]) ===> [111, 222]
-take_upto(-1, []) ===> []
-take_upto(-1, [111]) ===> [111]
-take_upto(-1, [111, 222]) ===> [111, 222]
+take_upto(int.min_int, []) ===> <<exception>>
+take_upto(int.min_int, [111]) ===> <<exception>>
+take_upto(int.min_int, [111, 222]) ===> <<exception>>
+take_upto(-1, []) ===> <<exception>>
+take_upto(-1, [111]) ===> <<exception>>
+take_upto(-1, [111, 222]) ===> <<exception>>
take_upto(0, []) ===> []
take_upto(0, [111]) ===> []
take_upto(0, [111, 222]) ===> []
@@ -18,12 +18,12 @@ take_upto(int.max_int, []) ===> []
take_upto(int.max_int, [111]) ===> [111]
take_upto(int.max_int, [111, 222]) ===> [111, 222]
-split_upto(int.min_int, []) ===> ([], [])
-split_upto(int.min_int, [111]) ===> ([], [111])
-split_upto(int.min_int, [111, 222]) ===> ([], [111, 222])
-split_upto(-1, []) ===> ([], [])
-split_upto(-1, [111]) ===> ([], [111])
-split_upto(-1, [111, 222]) ===> ([], [111, 222])
+split_upto(int.min_int, []) ===> <<exception>>
+split_upto(int.min_int, [111]) ===> <<exception>>
+split_upto(int.min_int, [111, 222]) ===> <<exception>>
+split_upto(-1, []) ===> <<exception>>
+split_upto(-1, [111]) ===> <<exception>>
+split_upto(-1, [111, 222]) ===> <<exception>>
split_upto(0, []) ===> ([], [])
split_upto(0, [111]) ===> ([], [111])
split_upto(0, [111, 222]) ===> ([], [111, 222])
diff --git a/tests/hard_coded/take_split_upto.m b/tests/hard_coded/take_split_upto.m
index b7703b5..0adc7e5 100644
--- a/tests/hard_coded/take_split_upto.m
+++ b/tests/hard_coded/take_split_upto.m
@@ -9,7 +9,7 @@
:- import_module io.
-:- pred main(io::di, io::uo) is det.
+:- pred main(io::di, io::uo) is cc_multi.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
@@ -17,6 +17,7 @@
:- implementation.
:- import_module assoc_list.
+:- import_module exception.
:- import_module int.
:- import_module list.
:- import_module maybe.
@@ -30,21 +31,37 @@ main(!IO) :-
io.nl(!IO),
list.foldl(run_split_upto_test, tests, !IO).
-:- pred run_take_upto_test(pair(int, list(int))::in, io::di, io::uo) is det.
+:- pred run_take_upto_test(pair(int, list(int))::in, io::di, io::uo)
+ is cc_multi.
run_take_upto_test(N - List, !IO) :-
NStr = describe_int(N),
io.format("take_upto(%s, %s) ===> ", [s(NStr), s(string(List))], !IO),
- list.take_upto(N, List, Start),
- io.format("%s\n", [s(string(Start))], !IO).
+ (
+ try [] (
+ list.take_upto(N, List, Start)
+ )
+ then
+ io.format("%s\n", [s(string(Start))], !IO)
+ catch_any _ ->
+ io.write_string("<<exception>>\n", !IO)
+ ).
-:- pred run_split_upto_test(pair(int, list(int))::in, io::di, io::uo) is det.
+:- pred run_split_upto_test(pair(int, list(int))::in, io::di, io::uo)
+ is cc_multi.
run_split_upto_test(N - List, !IO) :-
NStr = describe_int(N),
io.format("split_upto(%s, %s) ===> ", [s(NStr), s(string(List))], !IO),
- list.split_upto(N, List, Start, End),
- io.format("(%s, %s)\n", [s(string(Start)), s(string(End))], !IO).
+ (
+ try [] (
+ list.split_upto(N, List, Start, End)
+ )
+ then
+ io.format("(%s, %s)\n", [s(string(Start)), s(string(End))], !IO)
+ catch_any _ ->
+ io.write_string("<<exception>>\n", !IO)
+ ).
%---------------------------------------------------------------------------%
More information about the reviews
mailing list