[m-rev.] for review: add string.contains_match/2
Julien Fischer
jfischer at opturion.com
Mon Jul 25 15:38:10 AEST 2022
For review by anyone.
---------------------
Add string.contains_match/2.
Add a new predicate that tests if string contains any characters that succeed
for a given test predicate.
library/string.m:
Add the new predicate.
compiler/options.m:
Replace the predicate string_contains_whitespace/1 defined here
with a call to the new library predicate.
NEWS:
Announce the new predicate.
tests/hard_coded/Mmakefile:
tests/hard_coded/string_contains_match.{m,exp}:
Add a test of the new predicate.
Julien.
diff --git a/NEWS b/NEWS
index 79317b8..bd9f2f6 100644
--- a/NEWS
+++ b/NEWS
@@ -353,6 +353,12 @@ Changes to the Mercury standard library
- pred `empty/1`
+### Changes to the `string` module
+
+* The following predicate has been added:
+
+ - pred `contains_match/2`
+
### Changes to the `tree_bitset` module
* The following obsolete predicates has been removed:
diff --git a/compiler/options.m b/compiler/options.m
index 9ac6043..99ebfc7 100644
--- a/compiler/options.m
+++ b/compiler/options.m
@@ -4108,7 +4108,7 @@ quote_arg(Arg0) = Arg :-
% test whether we are using a Unix or Windows shell.
( if dir.use_windows_paths then
( if
- ( string_contains_whitespace(Arg0)
+ ( string.contains_match(char.is_whitespace, Arg0)
; Arg0 = ""
)
then
@@ -4141,15 +4141,6 @@ quote_arg(Arg0) = Arg :-
)
).
-:- pred string_contains_whitespace(string::in) is semidet.
-
-string_contains_whitespace(Str) :-
- Chars = string.to_char_list(Str),
- some [Char] (
- list.member(Char, Chars),
- char.is_whitespace(Char)
- ).
-
:- func quote_arg_unix(list(char)) = list(char).
quote_arg_unix([]) = [].
diff --git a/library/string.m b/library/string.m
index 2fdb245..0750d07 100644
--- a/library/string.m
+++ b/library/string.m
@@ -578,6 +578,14 @@
%
:- pred all_match(pred(char)::in(pred(in) is semidet), string::in) is semidet.
+ % contains_match(TestPred, String):
+ %
+ % True iff String contains at least one code point that satisfies
+ % TestPred.
+ %
+:- pred contains_match(pred(char)::in(pred(in) is semidet), string::in)
+ is semidet.
+
% contains_char(String, Char):
%
% Succeed if the code point Char occurs in String.
@@ -3292,6 +3300,22 @@ all_match_loop(P, String, Cur) :-
%---------------------%
+contains_match(P, String) :-
+ contains_match_loop(P, String, 0).
+
+:- pred contains_match_loop(pred(char)::in(pred(in) is semidet), string::in,
+ int::in) is semidet.
+
+contains_match_loop(P, String, Cur) :-
+ unsafe_index_next_repl(String, Cur, Next, Char, not_replaced),
+ ( if P(Char) then
+ true
+ else
+ contains_match_loop(P, String, Next)
+ ).
+
+%---------------------%
+
:- pragma foreign_proc("C",
contains_char(Str::in, Ch::in),
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
diff --git a/tests/hard_coded/Mmakefile b/tests/hard_coded/Mmakefile
index 2385e34..caa47e9 100644
--- a/tests/hard_coded/Mmakefile
+++ b/tests/hard_coded/Mmakefile
@@ -385,6 +385,7 @@ ORDINARY_PROGS = \
string_codepoint \
string_codepoint_offset_ilseq \
string_compare_substrings \
+ string_contains_match \
string_count_codepoints_ilseq \
string_first_char \
string_fold_ilseq \
diff --git a/tests/hard_coded/string_contains_match.exp b/tests/hard_coded/string_contains_match.exp
index e69de29..d6c8009 100644
--- a/tests/hard_coded/string_contains_match.exp
+++ b/tests/hard_coded/string_contains_match.exp
@@ -0,0 +1,9 @@
+contains_match(is_whitespace, "") ==> false.
+contains_match(is_whitespace, "abc") ==> false.
+contains_match(is_whitespace, " abc") ==> true.
+contains_match(is_whitespace, "a bc") ==> true.
+contains_match(is_whitespace, "abc ") ==> true.
+contains_match(is_whitespace, "μῆνιν ἄειδε θεὰ Πηληϊάδεω Ἀχιλῆος") ==> true.
+contains_match(is_chess_piece, "♜ ♞ ♝ ♛ ♚ ♝ ♞ ♜") ==> true.
+contains_match(is_chess_piece, "abc♜ def") ==> true.
+contains_match(is_chess_piece, "no chess pieces here!") ==> false.
diff --git a/tests/hard_coded/string_contains_match.m b/tests/hard_coded/string_contains_match.m
index e69de29..c88cd29 100644
--- a/tests/hard_coded/string_contains_match.m
+++ b/tests/hard_coded/string_contains_match.m
@@ -0,0 +1,61 @@
+%---------------------------------------------------------------------------%
+% vim: ts=4 sw=4 et ft=mercury
+%---------------------------------------------------------------------------%
+% A test of string.contains_match/2.
+%---------------------------------------------------------------------------%
+
+:- module string_contains_match.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module char.
+:- import_module int.
+:- import_module list.
+:- import_module string.
+
+%---------------------------------------------------------------------------%
+
+main(!IO) :-
+ test_contains_match(is_whitespace, "is_whitespace", "", !IO),
+ test_contains_match(is_whitespace, "is_whitespace", "abc", !IO),
+ test_contains_match(is_whitespace, "is_whitespace", " abc", !IO),
+ test_contains_match(is_whitespace, "is_whitespace", "a bc", !IO),
+ test_contains_match(is_whitespace, "is_whitespace", "abc ", !IO),
+ test_contains_match(is_whitespace, "is_whitespace",
+ "μῆνιν ἄειδε θεὰ Πηληϊάδεω Ἀχιλῆος", !IO),
+ test_contains_match(is_chess_piece, "is_chess_piece",
+ "♜ ♞ ♝ ♛ ♚ ♝ ♞ ♜", !IO),
+ test_contains_match(is_chess_piece, "is_chess_piece",
+ "abc♜ def", !IO),
+ test_contains_match(is_chess_piece, "is_chess_piece",
+ "no chess pieces here!", !IO).
+
+:- pred test_contains_match(pred(char)::in(pred(in) is semidet),
+ string::in, string::in, io::di, io::uo) is det.
+
+test_contains_match(Pred, PredName, String, !IO) :-
+ ( if string.contains_match(Pred, String) then
+ Result = "true"
+ else
+ Result = "false"
+ ),
+ io.format("contains_match(%s, %s) ==> %s.\n",
+ [s(PredName), s(string(String)), s(Result)], !IO).
+
+:- pred is_chess_piece(char::in) is semidet.
+
+is_chess_piece(Char) :-
+ char.to_int(Char, CodePoint),
+ CodePoint >= 0x2654, CodePoint =< 0x265F.
+
+%---------------------------------------------------------------------------%
+:- end_module string_contains_match.
+%---------------------------------------------------------------------------%
More information about the reviews
mailing list