Prolog:从谓词列表中生成一组所有基础术语

时间:2014-03-03 15:22:11

标签: prolog

鉴于以下事实:

female(alice).
male(bob).
male(charlie).
lives(alice,oxford).
lives(bob,oxford).
lives(charlie,cambridge).

我想要生成集合:

[alice,bob,charlie,oxford,cambridge].

我知道如何为单个谓词:

?- setof(X, male(X), S).
S = [bob, charlie].

但我不知道如何概括这一点。目的是使用谓词列表查询程序:

f([male/1,female/1,lives/2]).

我试图概括上述'setof'语句:

g(P,1) :-
  Atom = [P,X],
  Goal =..Atom,
  setof(X, Goal(X, Y), S),
  write(S).

g(P,2).

f([]).

f([H|T]) :-
  H = P/A,
  g(P,A),
  f(T).

但是这没用。

有人可以帮忙吗?

1 个答案:

答案 0 :(得分:3)

你快到了。使用callapply谓词可以在Prolog中实现Higher-order programming。这是call/1的版本,由ISO标准化:

get_ground_args(Goal, Args) :-
    findall(X, (call(Goal), Goal =.. [_|GoalArgs], member(X, GoalArgs)), Args).

示例:

?- get_ground_args(lives(_,_), Args).
Args = [alice, oxford, bob, oxford, charlie, cambridge].

现在要将其与原始设置相关联,请使用length/2在嵌套setof / findall内生成初始参数:

all_ground_args(Preds, Args) :-
    setof(X, (findall(Y, (member(Pred/Arity, Preds),
                          length(GoalArgs, Arity),
                          Goal =.. [Pred|GoalArgs],
                          get_ground_args(Goal, GroundArgs),
                          member(Y, GroundArgs)),
                      AllArgs),
              member(X, AllArgs)),
          Args).

演示:

?- all_ground_args([male/1,female/1,lives/2], Args).
Args = [alice, bob, cambridge, charlie, oxford].

(当谓词具有非地面参数时,所有这些都可能会失败。)