如何确定prolog"compund术语"内部是否有特定的"原子"?



我想要一个谓词来判断一个特定的原子(比如x(是否出现在复合项中,无论嵌套得多么深。

我试图阅读有关 https://www.swi-prolog.org/pldoc/man?section=manipterm 给出的谓词的信息。我认为这将涉及使用functor/3../2回避地走复合术语。有没有更简单的方法,或者一些库可以做到这一点?

Carlo 的优雅答案适用于 SWI-Prolog,但不可移植,因为 ISO Prologarg/3谓词的标准规范(大多数 Prolog 系统实现(要求其第一个参数绑定到整数,防止将其用作复合项参数的可反向生成器。更便携的替代方案是:

haystack_needle(H, N) :-
H == N.
haystack_needle(H, N) :-
functor(H, _, A),
between(1, A, I),
arg(I, H, A),
haystack_needle(A, N).

ISO Prolog 标准中未指定between/3谓词,但它是事实上的标准谓词,通常作为内置谓词或库谓词提供。

忽略循环项,我会使用 ==/2,化合物/1 和 arg/3

haystack_needle(H,N) :- H==N.
haystack_needle(H,N) :- compound(H),arg(_,H,A),haystack_needle(A,N).

haystack_needle/2 将成功多次,然后允许计数发生次数:

?- aggregate(count, haystack_needle(t(a,x,b,[x,x,x]),x), C).
C = 4.

注意,针不需要是原子...

您可以使用 once/1 来判断针是否出现在大海捞针中:

?- once(haystack_needle(t(a,x,b,[x,x,x]),x)).
true.
?- once(haystack_needle(t(a,x,b,[x,x,x]),z)).
false.

正如Paulo所指出的,arg/3无法在符合ISO标准的Prologs中适当地发挥作用。 一个可移植的替代方案(交换参数,除了避免混淆之外没有其他目的(可能是

needle_haystack(N,H) :- N==H.
needle_haystack(N,H) :- H=..[_|As],member(A,As),needle_haystack(N,A).

当然,如果会员/2 可用:)

最新更新