我有一个prolog程序:
link(liverpool,preston).
link(liverpool,manchester).
link(preston,lancaster).
link(preston,manchester).
link(lancaster,carlisle).
link(lancaster,leeds).
link(carlisle,leeds).
link(manchester,leeds).
%checks to see if X is in the supplied list
inlist( X, [X|_]).
inlist( X, [_|Ys]) :- inlist( X, Ys).
merge([],L,L).
merge([H|T],BList,CList):-
inlist(H,BList),
merge(T,BList,CList).
merge([H|T],BList,[H|CList]):-
merge(T,BList,CList),
not(inlist(H,BList)).
合并工作,如果我这样调用它:
merge([a,b,c],[d,e,f],Result). --> [a,b,c,d,e,f]
或者更重要的是,它被设计用来解决的问题:
merge([a,b,c],[a,d,e,f],Result). --> [a,b,c,d,e,f]
但是如果我像这样调用merge:
merge(X,[d,e,f],[a,b,c,d,e,f]).
存在堆栈溢出。对于设计为单向工作的函数来说,这种行为通常是可以接受的吗?还是说函数应该以两种方式工作?
如果你像这样调用它,Edit: merge可以工作:
merge([a,b,c],X,[a,b,c,d,e,f]). --> [d,e,f]
首先,不应该调用这些"函数"。"谓词"是正确的术语。
通常希望Prolog谓词"双向"工作。但在特定情况下,这并不总是可能的,也不值得付出努力。
可以使用模式声明来告知谓词的使用方式。这些声明约定因系统而异。这些声明主要作为程序员的文档,很少被编译器使用,但可以被测试框架和其他辅助工具使用。
模式声明约定示例:
- SWI-Prolog: http://www.swi-prolog.org/pldoc/man?section=modes
- ECLiPSe CLP: http://eclipseclp.org/doc/applications/tutorial003.html#toc10(滚动到2.7.3模式声明)
还有一个约定(例如,在"The Craft of Prolog"中有描述),谓词的输入参数先出现,输出参数最后出现。