]> Repositorios git - scryer-prolog.git/commitdiff
ADDED: countall/2, for compatibility with GNU Prolog.
authorMarkus Triska <[email protected]>
Thu, 13 Jul 2023 21:08:13 +0000 (23:08 +0200)
committerMarkus Triska <[email protected]>
Thu, 13 Jul 2023 21:08:13 +0000 (23:08 +0200)
Example:

    ?- countall(member(X, "abc"), N).
       N = 3.

src/lib/iso_ext.pl

index 8b3e8dc37ac8f2d95146f753d931193598c32c3e..afc28969a9a4f5250ae540ddfe8632646d65adc0 100644 (file)
@@ -15,9 +15,10 @@ but they're not part of the ISO Prolog standard at the moment.
                     partial_string_tail/2,
                     setup_call_cleanup/3,
                     call_nth/2,
+                    countall/2,
                     copy_term_nat/2,
-                           asserta/2,
-                           assertz/2]).
+                    asserta/2,
+                    assertz/2]).
 
 :- use_module(library(error), [can_be/2,
                                domain_error/3,
@@ -339,6 +340,36 @@ call_nth_nesting(C, ID) :-
     bb_put(ID, 0),
     bb_put(i_call_nth_counter, C).
 
+%% countall(Goal, N).
+%
+% countall(Goal, N) counts all solutions of Goal and unifies N with
+% this number of solutions. This predicate always succeeds once.
+
+:- meta_predicate(countall(0, ?)).
+
+countall(Goal, N) :-
+    can_be(integer, N),
+    (   integer(N) ->
+        (   N < 0 ->
+            domain_error(not_less_than_zero, N, countall/2)
+        ;   N > 0
+        )
+    ;   true
+    ),
+    setup_call_cleanup(call_nth_nesting(C, ID),
+                       (   (   Goal,
+                               bb_get(ID, N0),
+                               N1 is N0 + 1,
+                               bb_put(ID, N1),
+                               false
+                           ;   bb_get(ID, N)
+                           )
+                       ),
+                       (   bb_get(i_call_nth_counter, C) ->
+                           C1 is C - 1,
+                           bb_put(i_call_nth_counter, C1)
+                       ;   true
+                       )).
 
 %% copy_term_nat(Source, Dest)
 %