[m-rev.] for review: Improve `integer' module interface.

Peter Wang novalazy at gmail.com
Fri Feb 13 16:59:07 AEDT 2015


Add integer.to_int/2 which fails instead of throwing an exception if the
value cannot be represented as an `int'.

Deprecate semidet functions:
	from_string/1, from_base_string/2, int/1

Add semidet predicates to replace them:
	from_string/2, from_base_string/3, det_to_int/1

library/integer.m:
	As above.

library/string.format.m:
	Conform to changes.

NEWS:
	Announce changes.

diff --git a/NEWS b/NEWS
index d3e35d8..bfa7323 100644
--- a/NEWS
+++ b/NEWS
@@ -100,6 +100,19 @@ Changes to the Mercury standard library:
 
    - infinity/0
 
+* The following predicates and functions have been added to the integer module:
+
+   - from_string/2
+   - from_base_string/3
+   - to_int/2
+   - det_to_int/1
+
+  The following functions in the integer module have been deprecated:
+
+   - from_string/1
+   - from_base_string/2
+   - int/1
+
 * The following predicates and functions have been added to the require module:
 
    - error/2
diff --git a/library/integer.m b/library/integer.m
index 4312c33..eb962be 100644
--- a/library/integer.m
+++ b/library/integer.m
@@ -38,7 +38,10 @@
 
 :- func to_string(integer) = string.
 
+:- pred from_string(string::in, integer::out) is semidet.
+
 :- func from_string(string::in) = (integer::out) is semidet.
+:- pragma obsolete(from_string/1).
 
 :- func det_from_string(string) = integer.
 
@@ -46,9 +49,12 @@
     % The string must contain one or more digits in the specified base,
     % optionally preceded by a plus or minus sign.  For bases > 10, digits
     % 10 to 35 are represented by the letters A-Z or a-z.  If the string
-    % does not match this syntax then the function fails.
+    % does not match this syntax then the predicate fails.
     %
+:- pred from_base_string(int::in, string::in, integer::out) is semidet.
+
 :- func from_base_string(int, string) = integer is semidet.
+:- pragma obsolete(from_base_string/2).
 
     % As above but throws an exception rather than failing.
     %
@@ -95,7 +101,18 @@
 :- func pow(integer, integer) = integer.
 
 :- func float(integer) = float.
+
+    % Convert an integer to an int.
+    % Fails if the integer is not in the range [min_int, max_int].
+    %
+:- pred to_int(integer::in, int::out) is semidet.
+
+    % As above but throws an exception rather than failing.
+    %
+:- func det_to_int(integer) = int.
+
 :- func int(integer) = int.
+:- pragma obsolete(int/1).
 
 :- func zero = integer.
 
@@ -1038,17 +1055,21 @@ float_list(_, Accum, []) = Accum.
 float_list(FBase, Accum, [H | T]) =
     float_list(FBase, Accum * FBase + float.float(H), T).
 
-integer.int(Integer) = Int :-
-    (
-        Integer >= integer(int.min_int),
-        Integer =< integer(int.max_int)
-    ->
-        Integer = i(_Sign, Digits),
-        Int = int_list(Digits, 0)
+integer.to_int(Integer, Int) :-
+    Integer >= integer(int.min_int),
+    Integer =< integer(int.max_int),
+    Integer = i(_Sign, Digits),
+    Int = int_list(Digits, 0).
+
+integer.det_to_int(Integer) = Int :-
+    ( integer.to_int(Integer, IntPrime) ->
+        Int = IntPrime
     ;
         error("integer.int: domain error (conversion would overflow)")
     ).
 
+integer.int(Integer) = integer.det_to_int(Integer).
+
 :- func int_list(list(int), int) = int.
 
 int_list([], Accum) = Accum.
@@ -1064,11 +1085,14 @@ integer.one = i(1, [1]).
 %
 
 integer.from_string(S) = Big :-
+    integer.from_string(S, Big).
+
+integer.from_string(S, Big) :-
     string.to_char_list(S, Cs),
     string_to_integer(Cs) = Big.
 
 integer.det_from_string(S) =
-    ( I = integer.from_string(S) ->
+    ( integer.from_string(S, I) ->
         I
     ;
         func_error(
@@ -1264,6 +1288,9 @@ printbase_pos_mul_list([X|Xs], Carry, Y) =
 %---------------------------------------------------------------------------%
 
 integer.from_base_string(Base, String) = Integer :-
+    integer.from_base_string(Base, String, Integer).
+
+integer.from_base_string(Base, String, Integer) :-
     string.index(String, 0, Char),
     Len = string.length(String),
     ( Char = ('-') ->
@@ -1291,7 +1318,7 @@ accumulate_integer(Base, Char, !N) :-
     !:N = (integer(Base) * !.N) + Digit.
 
 integer.det_from_base_string(Base, String) = Integer :-
-    ( Integer0 = integer.from_base_string(Base, String) ->
+    ( integer.from_base_string(Base, String, Integer0) ->
         Integer = Integer0
     ;
         error("integer.det_from_base_string")
diff --git a/library/string.format.m b/library/string.format.m
index d95e350..697d971 100644
--- a/library/string.format.m
+++ b/library/string.format.m
@@ -1084,7 +1084,7 @@ justify_string(Flags, MaybeWidth, Str) = JustifiedStr :-
 %
 % The input is an arbitrary precision integer because if either
 %
-% - the original number is a signed int, and its value is minint, or
+% - the original number is a signed int, and its value is min_int, or
 % - the original number is an unsigned int, and its value has the most
 %   significant bit set,
 %
@@ -1102,8 +1102,8 @@ justify_string(Flags, MaybeWidth, Str) = JustifiedStr :-
 abs_integer_to_octal(Num) = NumStr :-
     ( if Num > integer(0) then
         Integer8 = integer(8),
-        FrontDigitsStr = abs_int_to_octal(int(Num // Integer8)),
-        LastDigitStr = get_octal_digit(int(Num rem Integer8)),
+        FrontDigitsStr = abs_int_to_octal(det_to_int(Num // Integer8)),
+        LastDigitStr = get_octal_digit(det_to_int(Num rem Integer8)),
         NumStr = append(FrontDigitsStr, LastDigitStr)
     else
         NumStr = ""
@@ -1126,8 +1126,8 @@ abs_int_to_octal(Num) = NumStr :-
 abs_integer_to_decimal(Num) = NumStr :-
     ( if Num > integer(0) then
         Integer10 = integer(10),
-        FrontDigitsStr = abs_int_to_decimal(int(Num // Integer10)),
-        LastDigitStr = get_decimal_digit(int(Num rem Integer10)),
+        FrontDigitsStr = abs_int_to_decimal(det_to_int(Num // Integer10)),
+        LastDigitStr = get_decimal_digit(det_to_int(Num rem Integer10)),
         NumStr = append(FrontDigitsStr, LastDigitStr)
     else
         NumStr = ""
@@ -1153,8 +1153,8 @@ abs_int_to_decimal(Num) = NumStr :-
 abs_integer_to_hex_lc(Num) = NumStr :-
     ( if Num > integer(0) then
         Integer16 = integer(16),
-        FrontDigitsStr = abs_int_to_hex_lc(int(Num // Integer16)),
-        LastDigitStr = get_hex_digit_lc(int(Num rem Integer16)),
+        FrontDigitsStr = abs_int_to_hex_lc(det_to_int(Num // Integer16)),
+        LastDigitStr = get_hex_digit_lc(det_to_int(Num rem Integer16)),
         NumStr = append(FrontDigitsStr, LastDigitStr)
     else
         NumStr = ""
@@ -1163,8 +1163,8 @@ abs_integer_to_hex_lc(Num) = NumStr :-
 abs_integer_to_hex_uc(Num) = NumStr :-
     ( if Num > integer(0) then
         Integer16 = integer(16),
-        FrontDigitsStr = abs_int_to_hex_uc(int(Num // Integer16)),
-        LastDigitStr = get_hex_digit_uc(int(Num rem Integer16)),
+        FrontDigitsStr = abs_int_to_hex_uc(det_to_int(Num // Integer16)),
+        LastDigitStr = get_hex_digit_uc(det_to_int(Num rem Integer16)),
         NumStr = append(FrontDigitsStr, LastDigitStr)
     else
         NumStr = ""
-- 
2.1.2




More information about the reviews mailing list