这就是我会做的:
foo(A, B, C) :-
select(X, [A, B, C], L1),
select(Y, L1, [Z]),
bar(X, Y),
baz(Z).
我们的想法是,我们将使用 select/3(我最喜欢的谓词之一)重新调整这些参数的每个组合,然后对它们进行排列,我们可以将它们交给您关心的两个谓词。
这样做可能更清楚,但 L2 总是会包含一个元素,所以我只是在上面的上一个子句中匹配了它:
foo(A, B, C) :-
select(X, [A, B, C], L1),
select(Y, L1, L2),
select(Z, L2, _),
bar(X, Y),
baz(Z).
编辑:让我们处理任意 N。首先,我们需要一个 select_n/4,它为我提供列表中的 N 个项目。我打算用 DCG 来写这个,因为它对我来说更容易:
select_n([X|Xs], N) --> select(X), { succ(N0, N) }, select_n(Xs, N0).
select_n([], 0) --> [].
DCG 不仅是解析文本的好方法,也是将具有输入列表和输出列表的谓词串在一起的便捷方法。
现在我们可以使用这个帮助器来构建更通用的谓词版本。假设您为简单起见列出一个列表:
foo(L) :-
select_n(BarArgs, 2, L, L1),
select_n(BazArgs, 1, L1, []),
apply(bar, BarArgs),
apply(baz, BazArgs).
您可以将上面的2 和1 替换为您想要的任何内容,大概基于您想要调用的bar 和baz 的数量。
如果您不使用 SWI,或者只想使用 call/1,则必须先使用 univ 运算符 =.. 来构建术语,然后再使用 call/1:
foo(L) :-
select_n(BarArgs, 2, L, L1),
select_n(BazArgs, 1, L1, []),
Bar =.. [bar|BarArgs],
Baz =.. [baz|BazArgs],
call(Bar),
call(Baz).