[m-rev.] for review: document failrue conditions for list.split/4

Julien Fischer jfischer at opturion.com
Thu Jun 2 12:06:38 AEST 2016


For review by anyone.

I would also be intrested in feedback whether the current behaviour
of list.{drop,take} when their first argument is negative is intended.

-----------------

Document failure conditions for list.split/4.

Improve test coverage of list.split_list, list.drop and list.take.

library/list.m:
     Document the failure conditions for split_list/4.

     Document that det_split_list/4 will also throw an exception for N < 0.

tests/hard_coded/split_list.{m,exp}:
     Test for list.split_list/4.

tests/hard_coded/take_and_drop.m:
     Ditto for list.take/3 and list.drop/3.

tests/hard_coded/Mmakefile:
     Add the new tests.

Julien.

diff --git a/library/list.m b/library/list.m
index ddd5f96..2cb24f4 100644
--- a/library/list.m
+++ b/library/list.m
@@ -209,15 +209,16 @@
      % split_list(Len, List, Start, End):
      %
      % splits `List' into a prefix `Start' of length `Len', and a remainder
-    % `End'. See also: take, drop and split_upto.
+    % `End'. Fails if `Len' is not in 0 .. length(List).
+    % See also: take, drop and split_upto.
      %
  :- pred split_list(int::in, list(T)::in, list(T)::out, list(T)::out)
      is semidet.

      % det_split_list(Len, List, Start, End):
      %
-    % A deterministic version of split_list, which aborts instead
-    % of failing if Len > length(List).
+    % A deterministic version of split_list, which aborts instead of failing if
+    % `Len' is not in 0 .. length(List).
      %
  :- pred det_split_list(int::in, list(T)::in, list(T)::out, list(T)::out)
      is det.
diff --git a/tests/hard_coded/Mmakefile b/tests/hard_coded/Mmakefile
index ca2c3c1..6d7bb01 100644
--- a/tests/hard_coded/Mmakefile
+++ b/tests/hard_coded/Mmakefile
@@ -272,6 +272,7 @@ ORDINARY_PROGS =	\
  	space \
  	spawn_native \
  	special_char \
+	split_list \
  	stable_sort \
  	static_no_tag \
  	stdlib_init \
@@ -311,6 +312,7 @@ ORDINARY_PROGS =	\
  	switch_detect \
  	system_sort \
  	tag_switch_dup_label \
+	take_and_drop \
  	term_io_test \
  	term_to_univ_test \
  	test234_sorted_insert \
diff --git a/tests/hard_coded/split_list.exp b/tests/hard_coded/split_list.exp
index e69de29..d201d22 100644
--- a/tests/hard_coded/split_list.exp
+++ b/tests/hard_coded/split_list.exp
@@ -0,0 +1,13 @@
+split_list(-1, []) ==> <<FALSE>>
+split_list(-1, [111]) ==> <<FALSE>>
+split_list(-1, [111, 222]) ==> <<FALSE>>
+split_list(0, []) ==> ([], [])
+split_list(0, [111]) ==> ([], [111])
+split_list(0, [111, 222]) ==> ([], [111, 222])
+split_list(1, []) ==> <<FALSE>>
+split_list(1, [111]) ==> ([111], [])
+split_list(1, [111, 222]) ==> ([111], [222])
+split_list(2, []) ==> <<FALSE>>
+split_list(2, [111]) ==> <<FALSE>>
+split_list(2, [111, 222]) ==> ([111, 222], [])
+split_list(2, [111, 222, 333]) ==> ([111, 222], [333])
diff --git a/tests/hard_coded/split_list.m b/tests/hard_coded/split_list.m
index e69de29..76f064e 100644
--- a/tests/hard_coded/split_list.m
+++ b/tests/hard_coded/split_list.m
@@ -0,0 +1,49 @@
+%---------------------------------------------------------------------------%
+% vim: ts=4 sw=4 et ft=mercury
+%---------------------------------------------------------------------------%
+%
+% Test list.split_list/4.
+
+:- module split_list.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+:- import_module assoc_list.
+:- import_module list.
+:- import_module pair.
+:- import_module string.
+
+main(!IO) :-
+    list.foldl(run_test, tests, !IO).
+
+:- pred run_test(pair(int, list(int))::in, io::di, io::uo) is det.
+
+run_test(N - List, !IO) :-
+    io.format("split_list(%d, %s) ==> ", [i(N), s(string(List))], !IO),
+    ( if list.split_list(N, List, Start, End)
+    then io.format("(%s, %s)\n", [s(string(Start)), s(string(End))], !IO)
+    else io.write_string("<<FALSE>>\n", !IO)
+    ).
+
+:- func tests = assoc_list(int, list(int)).
+
+tests = [
+    -1 - [],
+    -1 - [111],
+    -1 - [111, 222],
+    0 - [],
+    0 - [111],
+    0 - [111, 222],
+    1 - [],
+    1 - [111],
+    1 - [111, 222],
+    2 - [],
+    2 - [111],
+    2 - [111, 222],
+    2 - [111, 222, 333]
+].
diff --git a/tests/hard_coded/take_and_drop.exp b/tests/hard_coded/take_and_drop.exp
index e69de29..8eb2abd 100644
--- a/tests/hard_coded/take_and_drop.exp
+++ b/tests/hard_coded/take_and_drop.exp
@@ -0,0 +1,33 @@
+take(-2, []) ==> []
+take(-2, [111]) ==> []
+take(-2, [111, 222]) ==> []
+take(-1, []) ==> []
+take(-1, [111]) ==> []
+take(-1, [111, 222]) ==> []
+take(0, []) ==> []
+take(0, [111]) ==> []
+take(0, [111, 222]) ==> []
+take(1, []) ==> <<FALSE>>
+take(1, [111]) ==> [111]
+take(1, [111, 222]) ==> [111]
+take(2, []) ==> <<FALSE>>
+take(2, [111]) ==> <<FALSE>>
+take(2, [111, 222]) ==> [111, 222]
+take(2, [111, 222, 333]) ==> [111, 222]
+
+drop(-2, []) ==> []
+drop(-2, [111]) ==> [111]
+drop(-2, [111, 222]) ==> [111, 222]
+drop(-1, []) ==> []
+drop(-1, [111]) ==> [111]
+drop(-1, [111, 222]) ==> [111, 222]
+drop(0, []) ==> []
+drop(0, [111]) ==> [111]
+drop(0, [111, 222]) ==> [111, 222]
+drop(1, []) ==> <<FALSE>>
+drop(1, [111]) ==> []
+drop(1, [111, 222]) ==> [222]
+drop(2, []) ==> <<FALSE>>
+drop(2, [111]) ==> <<FALSE>>
+drop(2, [111, 222]) ==> []
+drop(2, [111, 222, 333]) ==> [333]
diff --git a/tests/hard_coded/take_and_drop.m b/tests/hard_coded/take_and_drop.m
index e69de29..b648ee3 100644
--- a/tests/hard_coded/take_and_drop.m
+++ b/tests/hard_coded/take_and_drop.m
@@ -0,0 +1,56 @@
+%---------------------------------------------------------------------------%
+% vim: ts=4 sw=4 et ft=mercury
+%---------------------------------------------------------------------------%
+%
+% Test list.take/3 and list.drop/3.
+
+:- module take_and_drop.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+:- import_module assoc_list.
+:- import_module list.
+:- import_module pair.
+:- import_module string.
+
+main(!IO) :-
+    list.foldl(run_test("take", take), tests, !IO),
+    io.nl(!IO),
+    list.foldl(run_test("drop", drop), tests, !IO).
+
+:- pred run_test(string::in,
+    pred(int, list(T), list(T))::in(pred(in, in, out) is semidet),
+    pair(int, list(T))::in, io::di, io::uo) is det.
+
+run_test(Name, Pred, N - List, !IO) :-
+    io.format("%s(%d, %s) ==> ", [s(Name), i(N), s(string(List))], !IO),
+    ( if Pred(N, List, Result)
+    then io.format("%s\n", [s(string(Result))], !IO)
+    else io.write_string("<<FALSE>>\n", !IO)
+    ).
+
+:- func tests = assoc_list(int, list(int)).
+
+tests = [
+    -2 - [],
+    -2 - [111],
+    -2 - [111, 222],
+    -1 - [],
+    -1 - [111],
+    -1 - [111, 222],
+    0 - [],
+    0 - [111],
+    0 - [111, 222],
+    1 - [],
+    1 - [111],
+    1 - [111, 222],
+    2 - [],
+    2 - [111],
+    2 - [111, 222],
+    2 - [111, 222, 333]
+].


More information about the reviews mailing list