I want to write a prolog predicate that holds if the predicate appearing as first parameter holds for all elements of the list appering in second parameter. Here is something that I have tried:
?- listing(all).
all(pred(_), [A|B]) :-
pred(A),
all(pred(_), B).
all(pred(_), [x]) :-
pred(x).
Something like the following should return true. Is this possible in Prolog?
all(number, [3, 5 ,7]).
You can use call/n
[swi-doc]:
call(X, Y).
Given X=number
, and Y
is for example 3
, it will call number(3)
. In case X
is a term, like number(1)
, it calls it like number(1, 3)
, as if the predicate was "curried".
So you can implement your function as:
all(_, []).
all(P, [A|B]) :-
call(P, A),
all(P, B).
although for more efficient backtracking, it might be better to swap the parameters:
all(P, L) :-
all2(L, P).
all2([], _).
all2([A|B], P) :-
call(P, A),
all2(B, P).
But the predicate you here aim to implement already exists in some popular Prolog interpreters maplist/2
[swi-doc].
This will call the Goal
on all elements of the list, or fail if the predicate fails at some point.
You can also construct functors with (=..)/2
[swi-doc]. For example:
X =.. [number, 1, 3]
will result in X = number(1, 3)
. You can then use call call/1
[swi-doc] with the constructed functor to call the functor as if it was a predicate, like:
X =.. [number, 1, 3], call(X).
Note that the (=..)/2
predicate does not work with this "currying" of functors, for example:
?- X =.. [number(1), 3].
ERROR: Type error: `atom' expected, found `number(1)' (a compound)
ERROR: In:
ERROR: [8] _6428=..[number(1),3]
ERROR: [7] <user>
.