[m-rev.] for review: Add string.append(uo, in, in) mode.
Peter Wang
novalazy at gmail.com
Thu Oct 24 14:58:14 AEDT 2019
library/string.m:
Add string.append(uo, in, in) mode. The comment about it being
multi instead of semidet was written back when string.append was
implemented in terms of list.append.
Implement remove_suffix using the new procedure (more efficient).
Implement remove_suffix_if_present using remove_suffix
(more efficient).
Add comments about the argument orders of remove_suffix,
det_remove_suffix, remove_suffix_if_present.
---
library/string.m | 44 +++++++++++++++++++++++++++++++-------------
1 file changed, 31 insertions(+), 13 deletions(-)
diff --git a/library/string.m b/library/string.m
index e8e3bf672..56e242155 100644
--- a/library/string.m
+++ b/library/string.m
@@ -642,12 +642,8 @@
:- mode append(in, in, in) is semidet. % implied
:- mode append(in, uo, in) is semidet.
:- mode append(in, in, uo) is det.
+:- mode append(uo, in, in) is semidet.
:- mode append(out, out, in) is multi.
-% The following mode is semidet in the sense that it doesn't succeed more
-% than once - but it does create a choice-point, which means that the
-% compiler can't deduce that it is semidet. (It is also inefficient.)
-% Use remove_suffix instead.
-% :- mode append(out, in, in) is semidet.
% nondet_append(S1, S2, S3):
%
@@ -907,8 +903,10 @@
% remove_suffix(String, Suffix, Prefix):
%
- % The same as append(Prefix, Suffix, String) except that this is semidet
- % whereas append(out, in, in) is nondet.
+ % The same as append(Prefix, Suffix, String).
+ %
+ % WARNING: the argument order is inconsistent with both remove_prefix
+ % and remove_suffix_if_present.
%
:- pred remove_suffix(string::in, string::in, string::out) is semidet.
@@ -916,11 +914,17 @@
% remove_suffix, except it throws an exception if String does not end
% with Suffix.
%
+ % WARNING: the argument order is inconsistent with both remove_prefix
+ % and remove_suffix_if_present.
+ %
:- func det_remove_suffix(string, string) = string.
% remove_suffix_if_present(Suffix, String) returns `String' minus `Suffix'
% if `String' ends with `Suffix', and `String' if it doesn't.
%
+ % WARNING: the argument order differs from remove_suffix and
+ % det_remove_suffix.
+ %
:- func remove_suffix_if_present(string, string) = string.
%---------------------------------------------------------------------------%
@@ -3598,6 +3602,8 @@ append(S1::in, S2::uo, S3::in) :-
append_ioi(S1, S2, S3).
append(S1::in, S2::in, S3::uo) :-
append_iio(S1, S2, S3).
+append(S1::uo, S2::in, S3::in) :-
+ append_oii(S1, S2, S3).
append(S1::out, S2::out, S3::in) :-
nondet_append(S1, S2, S3).
@@ -3661,6 +3667,21 @@ append_ioi(S1, S2, S3) :-
S3 = list_to_binary([S1, S2])
").
+:- pred append_oii(string::uo, string::in, string::in) is semidet.
+
+append_oii(S1, S2, S3) :-
+ Len2 = length(S2),
+ Len3 = length(S3),
+ ( if
+ Len2 =< Len3,
+ Len1 = Len3 - Len2,
+ compare_substrings((=), S3, Len1, S2, 0, Len2)
+ then
+ unsafe_between(S3, 0, Len1, S1)
+ else
+ fail
+ ).
+
nondet_append(S1, S2, S3) :-
Len3 = length(S3),
nondet_append_2(0, Len3, S1, S2, S3).
@@ -4548,8 +4569,7 @@ remove_prefix_if_present(Prefix, String) = Out :-
).
remove_suffix(String, Suffix, Prefix) :-
- suffix(String, Suffix),
- left(String, length(String) - length(Suffix), Prefix).
+ append(Prefix, Suffix, String).
det_remove_suffix(String, Suffix) = Prefix :-
( if remove_suffix(String, Suffix, PrefixPrime) then
@@ -4559,10 +4579,8 @@ det_remove_suffix(String, Suffix) = Prefix :-
).
remove_suffix_if_present(Suffix, String) = Out :-
- LeftCount = length(String) - length(Suffix),
- split(String, LeftCount, LeftString, RightString),
- ( if RightString = Suffix then
- Out = LeftString
+ ( if remove_suffix(String, Suffix, Prefix) then
+ Out = Prefix
else
Out = String
).
--
2.23.0
More information about the reviews
mailing list