From 9590d5200c16f57b80cb71e9fd7118639c0a3f47 Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Thu, 13 Jul 2023 23:08:13 +0200 Subject: [PATCH] ADDED: countall/2, for compatibility with GNU Prolog. Example: ?- countall(member(X, "abc"), N). N = 3. --- src/lib/iso_ext.pl | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) 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) % -- 2.54.0