我正在尝试编写一个谓词 is_multi(M)
,定义为:
M
的每个元素都具有X/N
的形式,其中X
是一个原子,N
是大于0的整数;M
不包含两个同原子的元素,为了什么is_multi([]). is_multi([a / 2, b / 2]).
很满意,但是
is_multi([a, b/2]). is_multi([a/0, b/2]). is_multi([a/2, 2/4]) is_multi([a/2, b/3, a/2]) is_multi([a/3, b/-4, c/1])
不是。
这是我到目前为止所写的内容:
is_multi(M) :- M = [].
is_multi(M) :-
M = [Head|Tail],
Head = X/N,
integer(N),
N > 0,
is_multi(Tail).
但它不会比较具有相同原子的两个元素。例如,is_multi([a/2, a/3])
不满足。我被这个困住了一天;有人可以给我一些提示吗?
最佳答案
首先,您可以通过将一些统一从 body 移动到头部来大大简化您的代码。
is_multi([]).
is_multi([X/N|Tail]) :-
integer(N), N > 0,
is_multi(Tail).
清理它会发现你在这里没有做的一件事,在你的规范中检查 X
是一个原子。通过在正文中添加 atom(X)
来修复。
好的,所以这处理了基本形式,但不能确保原子不重复。最简单的做法是将其分成两项检查,一项检查每一项是否格式正确,另一项检查列表是否格式正确。事实上,我倾向于将 maplist/2
与检查单个元素的谓词一起使用。但您真正必须做的是这样的事情:
is_valid([]).
is_valid([X/_|T]) :- is_valid(T), \+ memberchk(X/_, T).
这只是说空列表是有效的,如果尾部是有效的,则如果 X over something 没有出现在尾部,则列表是有效的。
如果这就是您想要的,请停止阅读。如果您想重构,这就是我的处理方式:
well_formed(X/N) :- atom(X), integer(N), N > 0.
no_repeating_numerators([]).
no_repeating_numerators([X/_|T]) :- no_repeating_numerators(T), \+ memberchk(X/_, T).
is_multi(L) :- maplist(well_formed, L), no_repeating_numerators(L).
关于list - 如何添加和比较列表中的成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17667736/