您似乎已经通过规范化数据库很好地解决了您的问题。将列表[I_1, I_2, ..., I_n] 表示为事实items(I_1, I_2, ..., I_n). 很不方便。列表适用于(可能是有序的)具有 0 个或更多元素的集合;事实通常用于具有预设列数的表,每行一个事实。而这两种表示:
-
[a, b, c](列表)和
-
item(a). item(b). item(c).(事实表)
其实很相似。选择一个或另一个取决于您希望如何使用它,并且在您的程序中从一个转换为另一个非常容易(并且很常见)。例如,当您定义了 (2) 时,?- member(X, [a, b, c]). 与 ?- item(X). 大致相同。 the question you linked 的 Prolog 列表版本将是:
combo(L1, L2, X-Y) :-
member(X, L1),
member(Y, L2).
然后:
?- combo([1,2,3], [4,5], R).
R = 1-4 ;
R = 1-5 ;
R = 2-4 ;
R = 2-5 ;
R = 3-4 ;
R = 3-5.
写items([a, b, c]). 有点不方便(但仍然没有必要),所以你有一个参数,所有项目的列表。然后,你可以这样做:
?- items(Is),
member(X, Is).
如果你真的有 items(a, b, c). 之类的东西,并且你知道你正好有三个项目,你仍然可以这样做:
?- items(A, B, C),
member(X, [A, B, C]).
如果您在编译时不知道items 的数量,则需要在运行时检查程序。如果您的程序看起来像您的问题:
items1(1, 2, 3).
items2(4, 5).
然后你可以例如这样做:
?- current_predicate(items1/N), % figure out the arity of items1
length(Is, N), % make a list of that length
Fact =.. [items1|Is], % create a callable term
Fact, % call the term to instantiate Is
member(X, Is). % enumerate the list
如你所见,相当迂回。
还有一条评论:在 Prolog 中使用(A,B) 作为“元组”是不寻常的。对于一对,你通常会写A-B,如果你不知道你有多少元素,它通常只是一个列表,例如[A,B|Rest]。请参阅this answer 及其下方的 cmets 了解更多详情。