![](/img/trans.png)
[英]using throw(cut) and catch() to implement the cut in a meta-interpreter
[英]Is there a cut-less way to implement same_length/3?
假設我想斷言三個列表的長度相同。 我可以這樣做:
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) ).
我一直聽說如何盡可能避免切割,是否有可能在這里避免它?
作為一個額外的問題,我認為這些是綠色削減,因為最終的謂詞是完全關系的,這是真的嗎?
為什么不以相同的方式定義same_length/3
通常定義same_length/2
?
same_length([], [], []).
same_length([_| T1], [_| T2], [_| T3]) :-
same_length(T1, T2, T3).
在所有參數未綁定的情況下調用時可以正常工作:
?- same_length(L1, L2, L3).
L1 = L2, L2 = L3, L3 = [] ;
L1 = [_990],
L2 = [_996],
L3 = [_1002] ;
L1 = [_990, _1008],
L2 = [_996, _1014],
L3 = [_1002, _1020] ;
L1 = [_990, _1008, _1026],
L2 = [_996, _1014, _1032],
L3 = [_1002, _1020, _1038] ;
...
在您提及的情況下,沒有虛假的選擇點或非終止回溯:
?- length(L3, 3), same_length(L1, L2, L3).
L3 = [_1420, _1426, _1432],
L1 = [_1438, _1450, _1462],
L2 = [_1444, _1456, _1468].
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.