【发布时间】:2018-12-04 15:42:19
【问题描述】:
假设我想断言三个列表的长度相同。我可以这样做:
same_length(First, Second, Third) :-
same_length(First, Second),
same_length(Second, Third).
当 First 或 Second 被实例化时,这是正确的。当所有三个参数都被实例化时,它也可以工作!但是,像 length(Third, 3), same_length(First, Second, Third) 这样的调用会导致它返回带有选择点的正确答案(所有三个列表的长度都为 3),然后永远循环生成永远不会匹配的解决方案。
我写了一个我相信在任何情况下都能做正确事情的版本:
same_length(First, Second, Third) :-
/* naively calling same_length(First, Second), same_length(Second, Third) doesn't work,
because it will fail to terminate in the case where both First and Second are
uninstantiated.
by always giving the first same_length/2 clause a real list we prevent it from
generating infinite solutions */
( is_list(First), same_length(First, Second), same_length(First, Third), !
; is_list(Second), same_length(Second, First), same_length(Second, Third), !
; is_list(Third), same_length(Third, First), same_length(Third, Second), !
% if none of our arguments are instantiated then it's appropriate to not terminate:
; same_length(First, Second), same_length(Second, Third) ).
我一直听说应该尽可能避免切割,这里可以避免吗?
作为一个额外的问题,我认为这些是绿色削减,因为最终谓词是完全关系的,这是真的吗?
【问题讨论】:
-
“绿色削减”用于提高程序的效率——它们只是削减不可能导致解决方案的计算。 “红色削减”用于消除不需要的解决方案。它们也提高了效率,但它们也改变了程序的可能输出。换句话说,“绿色剪辑”不会改变程序的含义,但“红色剪辑”是程序的一个组成部分,可以产生预期的结果。
-
我曾经非常担心这样的情况,并产生了具有很多
var/1和ground/1的类似谓词(这基本上就是您在这里使用is_list/1所做的事情) .总是,@false 会出现并指出我的 frankenstein 谓词在奇怪的情况下无法表现的十几种新方式(带有实例化的头部和未实例化的尾部的列表,向后正确性等)现在我只做简单的事情并希望调试如果我在实践中偶然发现一个奇怪的实例化模式会更容易。 -
顺便说一句,我真的很喜欢你的问题,请继续提问!
-
same_length([_|_], _, []).循环。 -
@num1:您已经接受了一个答案,所以我认为这就是您想要的答案。我宁愿写
maplist(\_^_^_^true, Xs, Ys, Zs)。
标签: prolog logical-purity non-termination