List 序言;if和(停止)递归

List 序言;if和(停止)递归,list,recursion,prolog,construction,if-statement,List,Recursion,Prolog,Construction,If Statement,为了更好地理解prolog、列表和递归作为一个整体,我正在努力完成分配给自己的各种简单任务。 其中包括从列表中删除两个条目 我定义了一个规则: is_on(Item, [Ah|At]) :- Ah = Item; is_on(Item, At). 这将检查“项”是否在列表X上。所以我想我可以扩展它来定义一个filter\u双谓词: filter_doubles([Ah|At], Result) :- (not(is_on(Ah, At)) -> Result =

为了更好地理解prolog、列表和递归作为一个整体,我正在努力完成分配给自己的各种简单任务。 其中包括从列表中删除两个条目

我定义了一个规则:

is_on(Item, [Ah|At]) :- Ah = Item; is_on(Item, At).
这将检查“项”是否在列表X上。所以我想我可以扩展它来定义一个filter\u双谓词:

filter_doubles([Ah|At], Result) :-
    (not(is_on(Ah, At)) ->
        Result = [Ah|Result]
    ;
        filter_doubles(At, Result)
    ).
这对我来说非常有意义:如果Ah没有出现在列表的其余部分(它的尾部),那么使用列表构造将a添加到结果的前面,否则将递归到列表的其余部分。 显然,Prolog不这么认为:

47 ?- filter_doubles([1,2,3,3,4,2,1,1], Z).
Z = [3|**]. 

我是否认为这一点过于必要?

两个分支都需要递归,并且需要一个基本情况:

filter_doubles([], []).
filter_doubles([X|L], Result) :-
    (memberchk(X,L) ->
        filter_doubles(L, Result)
    ;
        filter_doubles(L, Result0),
        Result = [X|Result0]
    ).
Result=[Ah | Result]
似乎确实是一种命令式思维。在Prolog中的意思是“统一
Result
,其中第二个参数是
Result
”,它要么失败(与occurs check统一),要么生成“有理树”(在大多数Prolog中是一个带循环的图结构)

练习:使我发布的代码具有递归性


请注意,这将删除除最后一次出现的每个项以外的所有项。

在逻辑编程中,谓词中的递归通常使用多个规则处理。第一条规则描述递归基本情况,即其停止条件;其他规则,或者可能只是第二个规则,描述递归步骤

因此,您的
处于
规则(我已将其重命名为
包含
)通常以以下方式编写:

contains(Item, [Item | _]).
contains(Item, [_ | Tail]) :- contains(Item, Tail).
filter\u double
谓词可能会经历类似的重写。首先,空列表将对应于空结果

filter_doubles([], []).
然后,如果
出现在列表的
其余部分
中,则在列表的
其余部分
上重复出现,删除出现的

filter_doubles([Item | Rest], Result) :-
    contains(Item, Rest), !,
    filter_doubles(Rest, Result).
最后,如果
没有出现在列表的
Rest
中(因为前面的规则已经针对该情况签出),您可以使用列表构造将该
放在结果的前面,然后继续过滤列表的
Rest

filter_doubles([Item | Rest], [Item | Tail]) :- filter_doubles(Rest, Tail).

请注意,当您尝试使用诸如
Result=[Ah | Result]
之类的表达式执行累加时,Prolog会创建一个无限递归的数据结构:
Result
与一个以
Ah
为头、以
Result
为尾的列表相统一,它统一于一个以
Ah
为头、以
Result
为尾的列表,它统一于一个以
Ah
为头、以
Result
为尾的列表,依此类推;是的,没错,匆匆写了这篇文章,没有考虑到这一点。这也是一个语法错误(缺少paren),谓词是叫
filter\u double
还是
filter\u doubles
?我甚至还没有注意到
Result=[Ah | Result]
。对此,我用一些评论扩展了我的答案+是的,嗯,最终我决定自己解释一下。