2016-07-07 56 views
1

在这个问题上Can be this lisp function be implemented recursively?延伸的所有成员,是有可能在Prolog的所有组合,如果列表中表示类似以下内容:排列组合包括序言

items1(1, 2, 3). 
items2(4, 5). 

我能得到的答案与下面的数据格式:

items1(1). 
items1(2). 
items1(3). 

items2(4). 
items2(5). 

?- findall((A,B), (items1(A), items2(B)), L). 
L = [ (1, 4), (1, 5), (2, 4), (2, 5), (3, 4), (3, 5)]. 

我检查了http://www.swi-prolog.org/pldoc/man?predicate=permutation/2的置换谓词,但这是为了不同的目的。

回答

1

你似乎已经很好地解决了你的问题,通过规范你的数据库。将代表[I_1, I_2, ..., I_n]列为事实items(I_1, I_2, ..., I_n).是不方便的。列表是指具有0个或更多元素的(可能是有序的)集合;事实通常用于具有预设列数的表格,每行一个事实。而这两种表示:

  1. [a, b, c](列表),并
  2. 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及其下方的注释。

+0

重要的答案。谢谢。 – rnso

+0

@rnso我仍然有点惊讶,这个Lisp版本是如此迂回。必须有一个更简单的方法来做到这一点.... – 2016-07-07 08:15:21

+0

像您这样的更有经验的人可以对Prolog vs Lisp发表评论。你早些时候已经发布过吗? – rnso