Prolog - 了解 cut 的使用

Prolog - understandig the use of cut

cut的用法我看不太清楚。例如在这种情况下:flatten,真的需要吗?即使没有两个 cut 谓词(我尝试删除),它也对我有用。哪些情况会导致回溯到cut? 删除削减你有书的相同实现 "The art of prolog" (Shapiro E.,Sterling L.) 即:

flatten([X|Xs],Ys) :-
    flatten(X,Ysl), 
    flatten(Xs,Ys2), 
    append(Ys1,Ys2,Ys).
flatten(X,[X]) :- 
    constant(X), 
    X\=[].
flatten([],[]).

这引出了另一个问题:是否有必要在第二个子句中检查它是否不是列表?如果它是单个术语,则不会与第一个子句统一……不是吗?

您问题中链接的程序使用 cut ! 运算符来防止答案中的代码与其他子句统一。如果没有这些削减 flatten2/2 从答案中将统一第一个参数中的空列表与第一个和第三个子句,即

flatten2([], []) :- !.
flatten2(L, [L]).

同样,如果第二个子句中没有 cut,flatten2/2 会在子句第二个和第三个中统一一个非空列表,从而导致不正确的行为。

另一方面,您的代码有明确的检查以确保 flatten/2 的每个子句处理一个特定情况:

  • 第一个子句递归地展平非空列表
  • 第二个子句从空列表以外的常量创建单项列表
  • 第三个子句"flattens"空列表。

由于每个子句仅适用于左侧的一种类型的项目,因此没有必要进行剪切。您可以通过切换第二个和第三个子句并在匹配空列表后添加一个剪切来重写您的代码,但我强烈建议不要这样做 (demo)。

is it necessary in the second clause to check if it's not a list?

此检查是必要的,因为空列表 [] 被视为常量,因此当空列表出现在被展平的列表 (demo) 中时,您的程序会出现不正确的行为。