From: Markus Triska Date: Sun, 23 Aug 2020 20:13:11 +0000 (+0200) Subject: ADDED: First version of call_nth/2. X-Git-Tag: v0.9.0~174^2~6^2 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=79cb4cd6a55732b430e5a16ec195a9d051e78be3;p=scryer-prolog.git ADDED: First version of call_nth/2. A thread-safe implementation is possible for example with '$nb_setarg'/3 (see #390). --- diff --git a/README.md b/README.md index dab6a379..1ce4b829 100644 --- a/README.md +++ b/README.md @@ -450,7 +450,7 @@ The modules that ship with Scryer Prolog are also called Predicates for reasoning about environment variables. * [`iso_ext`](src/lib/iso_ext.pl) Conforming extensions to and candidates for inclusion in the Prolog - ISO standard, such as `setup_call_cleanup/3` and + ISO standard, such as `setup_call_cleanup/3`, `call_nth/2` and `call_with_inference_limit/3`. * [`crypto`](src/lib/crypto.pl) Cryptographically secure random numbers and hashes, HMAC-based key diff --git a/src/lib/iso_ext.pl b/src/lib/iso_ext.pl index e206fd0b..e5ba94c1 100644 --- a/src/lib/iso_ext.pl +++ b/src/lib/iso_ext.pl @@ -7,7 +7,9 @@ call_with_inference_limit/3, forall/2, partial_string/1, partial_string/3, partial_string_tail/2, setup_call_cleanup/3, - variant/2]). + call_nth/2, variant/2]). + +:- use_module(library(error), [can_be/2,domain_error/3]). forall(Generate, Test) :- \+ (Generate, \+ Test). @@ -161,3 +163,35 @@ partial_string_tail(String, Tail) :- '$partial_string_tail'(String, Tail) ; throw(error(type_error(partial_string, String), partial_string_tail/2)) ). + +:- dynamic(i_call_nth_nesting/2). +:- dynamic(i_call_nth_counter/1). + +call_nth(Goal, N) :- + can_be(integer, N), + ( integer(N), N =< 0, + domain_error(positive_integer, N, call_nth/2) + ; true + ), + setup_call_cleanup(call_nth_nesting(ID), + ( Goal, + retract(i_call_nth_nesting(ID,N0)), + N1 is N0 + 1, + asserta(i_call_nth_nesting(ID,N1)), + ( integer(N) -> + N = N1, + ! + ; N = N1 + ) + ), + ( retract(i_call_nth_nesting(ID,_)), + retract(i_call_nth_counter(ID)) + )). + +call_nth_nesting(ID) :- + ( i_call_nth_counter(ID0) -> + ID is ID0 + 1 + ; ID = 0 + ), + asserta(i_call_nth_nesting(ID, 0)), + asserta(i_call_nth_counter(ID)).