Reputation: 235
Giving the following facts and restriction :
car(red, 2000).
car(black, 1990).
car(blue, 2010).
millennials(car(_,Y)) :- (car(_,Y)), Y =< 1995.
red(car(C,_)) :- car(C,_), C == red.
Given a list [millennials, red]
, I would like to make a call such as:
checkRestriction([millennials, red], car(red, 2000) , L).
L = red
Which return a list of the conditions that are respected by the car passed as argument.
This is different from this thread: How to filter a list in Prolog with multiple conditions?, because all restriction don't have to be successful, the goal is only to return a list of successful restriction with the car passed as argument.
I tried the following:
checkRestriction([],_,[]).
checkRestriction([H|T], Car, List) :-
( H(Car)
-> append(L, H(Car), List),
checkRestriction(T, Car, List)
; checkRestriction(T, Car, List) ).
Which check is the restriction returns true with car as argument, and append in that case to a list the restriction itself, otherwise is simply call the predicate with the tail of the list, but I get compilation error.
Upvotes: 1
Views: 74
Reputation: 5509
The goal H(Car)
causes a compilation error because a variable cannot be used as predicate name in Prolog. To correct your code, you must construct goal terms as follows:
?- H = red, Car = car(red,2000), Goal =.. [H,Car].
H = red,
Car = car(red, 2000),
Goal = red(car(red, 2000)).
?- H = millennials, Car = car(red,2000), Goal =.. [H,Car].
H = millennials,
Car = car(red, 2000),
Goal = millennials(car(red, 2000)).
Thus, the correct code is:
checkRestriction([], _, []).
checkRestriction([H|T], Car, Result) :-
Goal =.. [H, Car],
( call(Goal)
-> Result = [H|List],
checkRestriction(T, Car, List)
; checkRestriction(T, Car, Result) ).
millennials(car(_,Y)) :- car(_,Y), Y =< 1995.
red(car(C,_)) :- car(C, _), C == red.
blue(car(C,_)) :- car(C, _), C == blue.
black(car(C,_)) :- car(C, _), C == black.
Running examples:
?- checkRestriction([millennials, red], car(red,2000), L).
L = [red].
?- checkRestriction([millennials, black], car(black,1990), L).
L = [millennials, black].
?- checkRestriction([millennials, blue], car(blue,2010), L).
L = [blue].
?- checkRestriction([millennials, black], car(blue,2010), L).
L = [].
Alternatively, you can use call/N
:
checkRestriction([], _, []).
checkRestriction([H|T], Car, Result) :-
( call(H, Car)
-> Result = [H|List],
checkRestriction(T, Car, List)
; checkRestriction(T, Car, Result) ).
Upvotes: 1
Reputation: 1005
See the include/3 predicate in library(apply). https://www.swi-prolog.org/pldoc/doc/_SWI_/library/apply.pl?show=src
Upvotes: 0