1

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]).
false
  • 10,264
  • 13
  • 101
  • 209
pii_ke
  • 2,811
  • 2
  • 20
  • 30
  • 1
    [`maplist(number,[3,5,7])`](https://stackoverflow.com/a/6683502/772868) – false Oct 12 '18 at 20:06
  • @false if I add a fact like `maplist(variable, [x, y, z, t]).` does it add a `variable/1` predicate (that holds for `x`,`y`,`z` and `t` atoms) to the knowledge base? Can you point me to some information that can help me concisely write predicates which hold for a given list of atoms? – pii_ke Oct 14 '18 at 13:21
  • that fact is a definition of a new predicate named `maplist`. probably not what you wanted. – Will Ness Oct 14 '18 at 15:30

1 Answers1

2

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>

.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • `(=..)/2` does not provide the same functionality as ``call/2` does. – false Oct 12 '18 at 19:20
  • @false: No I agree, it constructs a functor, it does not *call* the functor, nor does it perform "currying". It can however be usefull if the functor should contain more than seven arguments, since for example SWI-Prolog has no call with eight or nine parameters. Where do I give the impression that it does that? – Willem Van Onsem Oct 12 '18 at 19:22
  • Here: *You can also construct functors with (=..)/2 ... simply call call/1* this creates the impression that this is *also* a way to get the same results. Further it does not handle modules. – false Oct 12 '18 at 19:34