Prolog | findall with result list of another findall

You have a typo and a (few) logic errors.

The value of Code goes into a list of Code: CodeList. You have variable Code on first and third position. Use this:

findall(Code, (values1(Code, _, Value), Value > 1000), CodeList).

Run it:

?- findall(Code, (values1(Code, _, Value), Value > 1000), CodeList).
CodeList = ['AAA', 'BBB', 'BBB', 'CCC', 'DDD', 'AAA', 'CCC'].

Duplicate elements are removed by using the predicate setof/3 instead.

However, setof/3 demands that you indicate (“existentially quantify” with the caret notation: Value^Date^) the variables that shall be invisible outside the inner goal, otherwise backtracking over possible values of Value and Date will occur outside of setof/3:

?- setof(Code, Value^Date^(values1(Code, Date, Value), Value > 1000), CodeList).
CodeList = ['AAA', 'BBB', 'CCC', 'DDD'].

Now you just need to “join” any “code” with the “percentage” … inside of setof/3:

?- setof([Code,Percent], 
         Value^Date^(values1(Code, Date, Value),
                     Value > 1000,
                     values2(Code,Percent)),
         Set).

Set = [['AAA', '0.2'], ['BBB', '0.25'], ['CCC', '0.55'], ['DDD', '0.98']].

You can pack this into a predicate which backtracks over the setof/3 result:

gimme(Code, Percent) :-
   setof([Code,Percent], 
            Value^Date^(values1(Code, Date, Value),
                        Value > 1000,
                        values2(Code,Percent)),
            Set),
   member([Code,Percent],Set).

Note that the reuse of variables of Code and Percent inside setof/3 and in the call to member/2 s well is actually ok: These are not the same variables.

And so:

?- gimme(Code,Percent).
Code = 'AAA',
Percent = '0.2' ;
Code = 'BBB',
Percent = '0.25' ;
Code = 'CCC',
Percent = '0.55' ;
Code = 'DDD',
Percent = '0.98'.

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top