我只是从序言开始,尽管我认为我已经对如何使用它有了很好的了解,但我在这里遇到了麻烦。我有这样的规则:
foo(A, B, C) :- bar(A, B), baz(C).
foo(A, B, C) :- bar(A, C), baz(B).
foo(A, B, C) :- bar(B, A), baz(C).
% etc, etc, for all permutations of `A, B, C`
但是,真正的规则有3个以上的参数,将它们全部写出/生成它们将使我最终得到一个非常大的文件。有没有办法抽象这种模式?
答案 0 :(得分:4)
这就是我要做的:
@Library('name_of_repo')
import name.of.package.*
utils = new name_of_pipeline()
// here you can invoke
utils.myFunc(var)
这样的想法是,我们将使用select/3
(我最喜欢的谓词之一)重新组合这些参数的每种组合,然后对它们进行置换,我们就可以移交给您关心的两个谓词。
这样做可能更清楚,但是L2总是包含一个元素,因此我在上面的上一个子句中将其匹配:
foo(A, B, C) :-
select(X, [A, B, C], L1),
select(Y, L1, [Z]),
bar(X, Y),
baz(Z).
编辑:让我们处理任意N个。首先,我们需要一个foo(A, B, C) :-
select(X, [A, B, C], L1),
select(Y, L1, L2),
select(Z, L2, _),
bar(X, Y),
baz(Z).
,该列表为我提供了N个项目。我将使用DCG编写此文件,因为它对我来说更容易:
select_n/4
DCG不仅是解析文本的好方法,而且还是将具有输入列表和输出列表的谓词串在一起的便捷方法。
现在,我们可以使用此帮助程序来构建您的谓词的更一般的版本。假设您为简单起见列出了一个列表:
select_n([X|Xs], N) --> select(X), { succ(N0, N) }, select_n(Xs, N0).
select_n([], 0) --> [].
您可以用您想要的任何内容替换上面的foo(L) :-
select_n(BarArgs, 2, L, L1),
select_n(BazArgs, 1, L1, []),
apply(bar, BarArgs),
apply(baz, BazArgs).
和2
,大概是基于您要调用的1
和bar
的组合。< / p>
如果您不使用SWI,或者只想使用baz
,则必须在使用call/1
之前使用univ运算符=..
来构建术语:< / p>
call/1
答案 1 :(得分:1)
另一个答案已经很好。只是一些进一步的想法。
在Prolog中,为您的微语言编写小型解释器非常容易。这是解决原始问题的另一种(廉价)方法:
foo(A, B, C) :-
permutation([A, B, C], [X, Y, Z]),
bar(X, Y), baz(Z).
...并使用call
,您可以参数化bar
和baz
:
foo(Bar, Baz, A, B, C) :-
permutation([A, B, C], [X, Y, Z]),
call(Bar, X, Y), call(Baz, Z).
这意味着您现在可以(按名称)传递Arity 2为Bar
的任何谓词以及Arity 1为Baz
的任何谓词。而且,如果您有一个接受3个参数的谓词bar_x
,则可以尽早绑定第一个参数。例如,您可以将foo/5
称为:
?- foo(bar(hello), baz, 1, 2, 3).
这将为第一个解决方案评估bar(hello, 1, 2)
。
因此,现在唯一不平凡的问题是,您的界面是什么?您想如何写下您的查询?您是将这三个参数作为单独的参数还是作为列表提供?您是否希望参数化谓词?依此类推。