你似乎已经很好地解决了你的问题,通过规范你的数据库。将代表[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序言列表版本将是:
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及其下方的注释。
重要的答案。谢谢。 – rnso
@rnso我仍然有点惊讶,这个Lisp版本是如此迂回。必须有一个更简单的方法来做到这一点.... – 2016-07-07 08:15:21
像您这样的更有经验的人可以对Prolog vs Lisp发表评论。你早些时候已经发布过吗? – rnso