[m-rev.] for review: Deprecate string.append(out, out, in) mode.

Peter Wang novalazy at gmail.com
Thu Oct 24 14:58:13 AEDT 2019


Mark pointed out that the string.append(out, out, in) mode does not
match the forward modes. The simplest solution is to deprecate and
eventually remove it.

library/string.m:
    Deprecate string.append(out, out, in) mode.

    Add string.nondet_append/3 as its replacement.

    Add more documentation.

NEWS:
    Announce changes.

--------

Or should the replacement be called multi_append?


diff --git a/NEWS b/NEWS
index 2d0cae6ab..0c479fa74 100644
--- a/NEWS
+++ b/NEWS
@@ -429,12 +429,14 @@ Changes to the Mercury standard library:
    - to_rev_char_list/2
    - compare_substrings/6
    - unsafe_compare_substrings/6
+   - nondet_append/3
 
   The following procedures in the string module have been deprecated:
 
    - to_char_list(uo, in)
    - to_rev_char_list(uo, in)
    - from_char_list(out, in)
+   - append(out, out, in)
 
 * The following predicates have been added to the map module:
 
diff --git a/library/string.m b/library/string.m
index e9e4e4955..e8e3bf672 100644
--- a/library/string.m
+++ b/library/string.m
@@ -624,6 +624,20 @@
     %
 :- func append(string::in, string::in) = (string::uo) is det.
 
+    % append(S1, S2, S3):
+    %
+    % Append two strings together. S3 consists of the code units of S1
+    % followed by the code units of S2, in order.
+    %
+    % An ill-formed code unit sequence at the end of S1 may join with an
+    % ill-formed code unit sequence at the start of S2 to produce a valid
+    % encoding of a code point in S3.
+    %
+    % The append(out, out, in) mode is deprecated because it does not match
+    % the semantics of the forwards modes in the presence of ill-formed code
+    % unit sequences. Use nondet_append/3 instead.
+    %
+%:- pragma obsolete_proc(append(out, out, in), [nondet_append/3]).
 :- pred append(string, string, string).
 :- mode append(in, in, in) is semidet.  % implied
 :- mode append(in, uo, in) is semidet.
@@ -635,6 +649,14 @@
 % Use remove_suffix instead.
 % :- mode append(out, in, in) is semidet.
 
+    % nondet_append(S1, S2, S3):
+    %
+    % Non-deterministically return S1 and S2, where S1 ++ S2 = S3.
+    % S3 is split after each code point or code unit in an ill-formed sequence.
+    %
+:- pred nondet_append(string, string, string).
+:- mode nondet_append(out, out, in) is multi.
+
     % S1 ++ S2 = S :- append(S1, S2, S).
     %
     % Append two strings together using nicer inline syntax.
@@ -3577,7 +3599,7 @@ append(S1::in, S2::uo, S3::in) :-
 append(S1::in, S2::in, S3::uo) :-
     append_iio(S1, S2, S3).
 append(S1::out, S2::out, S3::in) :-
-    append_ooi(S1, S2, S3).
+    nondet_append(S1, S2, S3).
 
 :- pred append_iii(string::in, string::in, string::in) is semidet.
 
@@ -3639,22 +3661,20 @@ append_ioi(S1, S2, S3) :-
     S3 = list_to_binary([S1, S2])
 ").
 
-:- pred append_ooi(string::out, string::out, string::in) is multi.
-
-append_ooi(S1, S2, S3) :-
+nondet_append(S1, S2, S3) :-
     Len3 = length(S3),
-    append_ooi_2(0, Len3, S1, S2, S3).
+    nondet_append_2(0, Len3, S1, S2, S3).
 
-:- pred append_ooi_2(int::in, int::in, string::out, string::out,
+:- pred nondet_append_2(int::in, int::in, string::out, string::out,
     string::in) is multi.
 
-append_ooi_2(Start2, Len3, S1, S2, S3) :-
+nondet_append_2(Start2, Len3, S1, S2, S3) :-
     (
         unsafe_between(S3, 0, Start2, S1),
         unsafe_between(S3, Start2, Len3, S2)
     ;
         unsafe_index_next(S3, Start2, NextStart2, _Char),
-        append_ooi_2(NextStart2, Len3, S1, S2, S3)
+        nondet_append_2(NextStart2, Len3, S1, S2, S3)
     ).
 
 S1 ++ S2 = append(S1, S2).
-- 
2.23.0



More information about the reviews mailing list