From: Markus Triska Date: Thu, 13 Jul 2023 21:08:13 +0000 (+0200) Subject: ADDED: countall/2, for compatibility with GNU Prolog. X-Git-Tag: v0.9.2~57^2 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=9590d5200c16f57b80cb71e9fd7118639c0a3f47;p=scryer-prolog.git ADDED: countall/2, for compatibility with GNU Prolog. Example: ?- countall(member(X, "abc"), N). N = 3. --- diff --git a/src/lib/iso_ext.pl b/src/lib/iso_ext.pl index 8b3e8dc3..afc28969 100644 --- a/src/lib/iso_ext.pl +++ b/src/lib/iso_ext.pl @@ -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) %