0

我希望它像这样工作,然后d消失等。

?- remove_last_item([a,b,c,d], L).    
L = [a, b, c] ?    

有谁知道如何做到这一点,因为我得到了这条线,但是我应该添加什么其他线,这样
才能实现上述目标。

4

3 回答 3

3

通常,在 Prolog 中,要理解问题,就必须已经有了答案。所以你需要定义一个谓词,remove_last_item(A,B)这样BA没有最后一项。那么Prolog中的列表是什么?就像在 Lisp 中一样,它是在对的顶部递归定义的,带有特殊符号 - 空列表 - 表示“列表结束”。

这意味着什么?一对, '.'(A,B), 显然有两个部分。然后将该列表[a,b,c,d]编码为'.'(a,'.'(b,'.'(c,'.'(d,[])))). 这也可以写成[a|[b,c,d]], or [a,b|[c,d]], or [a,b,c|[d]], or [a,b,c,d|[]]。这a是列表的所谓“头”和[b,c,d]“尾”或“其余” [a,b,c,d]

所以现在我们只需从最简单的情况开始写下我们想要谓词说的内容:

remove_last_item([_A],[]).
remove_last_item([A|B],[A|C]):- B=[_|_], remove_last_item(B,C).

它写道,“从单例列表中删除最后一项会给我们留下一个空列表;从多个元素的列表中删除最后一项意味着从列表的其余部分中删除最后一项,在它的头部之后”。

编辑:另一种看待它的方式是“从顶部开始”:写下谓词必须遵循的一些等效“法则”:

remove_last_item(L,R):- is_list(L), is_list(R), same_head(L,R),
                        tail(L,L1), tail(R,R1), 
  remove_last_item(L1,R1).

我们仍然不“知道”什么remove_last_item “做什么”,我们只是写了一个它必须遵循的等效定律,对吧?但随后它就变成了我们所追求的定义本身。充实所有暗示性的名字,它变成了(熟悉的)

remove_last_item(L,R):- L=[A|L1], R=[A|R1], remove_last_item(L1,R1).

所以现在我们可以将其识别为列表的结构递归,只需添加一个终止子句,为其添加一些“实质”。

于 2012-04-21T20:17:38.390 回答
1
?- append(L, [_], [a,b,c,d]).

观察它[_]表示具有单个任意元素的列表,因此该查询询问“当我们将单个元素列表附加到它时,L会给出哪个列表?”[a,b,c,d]

于 2012-04-21T20:13:02.893 回答
0

另一种方法是让 prolog 进行递归.. 这表示'查找列表中列表项的索引不等于列表最后一项的索引的所有项(其索引与长度相同名单)。(无论如何使用 nth1 时.. nth0 不起作用...

rli(List, Res) :-
    length(List, Y),
    findall(Item, (nth1(Idx, List, Item), not(Idx =:= Y)), Res).
于 2012-04-21T20:40:28.307 回答