如何在序言中将谓词指定为另一个谓词的参数?

How to specify a predicate as parameter to another in prolog?

我想编写一个序言谓词,如果作为第一个参数出现的谓词对第二个参数中出现的列表的所有元素都成立,则该谓词成立。这是我尝试过的东西:

?- listing(all).
all(pred(_), [A|B]) :-
    pred(A),
    all(pred(_), B).
all(pred(_), [x]) :-
    pred(x).

类似下面的内容应该 return 正确。这在 Prolog 中可能吗?

all(number, [3, 5 ,7]).

您可以使用 call/<i>n</i> [swi-doc]:

call(X, Y).

给定X=number,例如Y3,它会调用number(3)。如果 X 是一个术语,例如 number(1),它会像 number(1, 3) 一样调用它,就好像谓词是“curried”。

因此您可以将您的功能实现为:

all(_, []).
all(P, [A|B]) :-
    <b>call(P, A),</b>
    all(P, B).

虽然为了更有效的回溯,交换参数可能会更好:

all(P, L) :-
    all2(L, P).

all2([], _).
all2([A|B], P) :-
    call(P, A),
    all2(B, P).

但是您在这里要实现的谓词已经存在于一些流行的 Prolog 解释器中 maplist/2 [swi-doc]

这将对列表的所有元素调用 Goal,或者如果谓词在某个点失败则失败。

您还可以使用 (=..)/2 [swi-doc] 构造函子。例如:

X =.. [number, 1, 3]

将导致 X = number(1, 3)。然后,您可以将 call call/1 [swi-doc] 与构造的仿函数一起使用来调用仿函数,就好像它是谓词一样,例如:

X =.. [number, 1, 3], call(X).

请注意,(=..)/2 谓词不适用于此 "currying" 函子,例如:

?- 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>

.