你似乎已經很好地解決了你的問題,通過規範你的數據庫。將代表[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