I’m using: SWI-Prolog version 8.1.9.
PREFACE: If the code looks ‘odd’ below, be aware I have to avoid formal dynamic goal calling predicates like ‘call/1’, etc. because the PEngines sandbox rejects such attempts resulting in a sandbox fatal error. That is why I’m taking the following unusual steps to “stitch” together a dynamic call. Also, the reason I want to pass the filter predicate inside a variable is because I have multiple filter predicates with the same arity. I’m only showing one of the filter predicate calls for the purposes of brevity.
The code below generates the following warning during a make
operation:
Warning: The predicates below are not defined. If these are defined
Warning: at runtime using assert/1, use :- dynamic Name/Arity.
Warning:
Warning: fsg_is_score_too_low/0, which is referenced by
Warning: 1-st clause of filter_score_group/2
However, the code below works properly and at runtime, instead of fsg_is_score_too_low
being called with zero arguments, it is called with 2 arguments as desired. I know this because when I trace out the code in the graphical debugger it shows a call to fsg_is_score_too_low/2
and not fsg_is_score_too_low/0
. The latter would fail anyways because no such 0-arity version of fsg_is_score_too_low
exists. Therefore, the compiler is throwing an incorrect warning. Fortunately, it is generating the correct code.
Here is the relevant code:
% Filter a score record by overall score.
% fsg_is_score_too_low(+ScoreGroup, +ScoreRecord)
fsg_is_score_too_low(_, ScoreRecord) :-
extract_overall_score_from_score_record_val(ScoreRecord, OverallScore),
OverallScore < 1,
!.
% Support predicate for findall() operation. Select the next score
% record that should not be filtered.
% filter_score_group_1(+FilterFunc, +ScoreGroup, -ScoreRecord_filtered)
filter_score_group_1(FilterFunc, ScoreGroup, ScoreRecord_filtered) :-
member(ScoreRecord_filtered, ScoreGroup),
CallFilter =.. [ FilterFunc, ScoreGroup, ScoreRecord_filtered ],
\+ CallFilter.
% ======= CALLING CODE ========
% filter_score_group(+ScoreGroup, -ScoreGroup_filtered)
filter_score_group(ScoreGroup, ScoreGroup_filtered) :-
% First filter by overall score to reduce processing time.
FilterFunc_1 = fsg_is_score_too_low,
findall(
ScoreRecord_filtered_1,
filter_score_group_1(
% Filter predicate.
FilterFunc_1,
% Input score group.
ScoreGroup,
ScoreRecord_filtered_1),
% Filtered score group.
ScoreGroup_filtered_1),
!.