Prolog:如何"长度(+, - )"删除保留列表的列表的未分配尾部?

时间:2014-08-07 12:24:16

标签: list prolog

再次成为Prolog的初学者: - }

我使用

按元素构建列表元素

(1)     member(NewElement,ListToBeFilled). 在重复的电话中,

(2)

ListToBeFilled = [NewElement|TmpListToBeFilled].

在递归调用中,如

something(...,TmpListToBeFilled).

(2)的具体例子

catch_all_nth1(List, AllNth, Counter, Result) :-
   [H|T] = List,
   NewCounter is Counter + 1,
   (
      0 is Counter mod AllNth
   ->
      Result = [H|Result1]      
   ;
      Result = Result1  
   ),
   catch_all_nth1(T,AllNth,NewCounter,Result1),
   !.
catch_all_nth1([], _, _, _).

结果我得到了一个类似

的列表
[E1, E2, E3, ..., Elast | _G12321].

当然,Tail是一个变量。 [顺便说一下:有没有更好的方法来填补 列表,直接避免"未分配的尾巴"?]

我现在正在寻找一种简单的方法来消除"未分配的尾巴"。

我发现:  Delete an unassigned member in list 建议使用:

exclude(var, ListWithVar, ListWithoutVar),!,

[发现这一点,但没有帮助,因为我最后不想要一个虚拟元素 Prolog list has uninstantiated tail, need to get rid of it]

我注意到使用长度\ 2消除了"未分配的尾部",以及附加功能 同样的名单仍然存在。

我的问题是:它是如何运作的?我想使用这种机制来消除未分配的尾部,而不使用新的变量... [在SWI Prolog'到现在为止我没有得到调试器 输入长度()?!]

示例:

Z=['a','b','c' | Y],
X = Z,
write(' X '),write(X),nl,
length(X,Tmp),
write(' X '),write(X),nl.

13 ?- test(X).
X [a,b,c|_G3453]
X [a,b,c]
X = [a, b, c] .

我认为X,一旦初始化就不能再改变了,你需要 一个新的变量,如exclude(var,ListWithVar,ListWithoutVar)。

如果有人向我解释这个伎俩会很高兴......

谢谢: - )

2 个答案:

答案 0 :(得分:0)

我认为应该这样做:

% case 1: end of list reached, replace final var with empty list
close_open_list(Uninstantiated_Var) :- 
    var(Uninstantiated_Var), !,
    Uninstantiated_Var = '[]'.

% case 2: not the end, recurse
close_open_list([_|Tail]) :- 
    close_open_list(Tail).


?- X=[1,2,3|_], close_open_list(X).
X = [1, 2, 3].

请注意,只使用变量X ..它只是通过列表进行递归,直到它到达最后的var,用一个空列表替换它,然后关闭它。然后X可以作为常规'关闭'列表。

编辑:一旦将列表元素分配给特定的内容,就无法更改。但是当列表构建为开放列表时,列表本身可以附加到。最后用_ _打开列表是构建列表元素而不需要新变量的好方法。例如

X=[1,2,3|_], memberchk(4, X), memberchk(5,X).
X = [1, 2, 3, 4, 5|_G378304]

在上面的示例中,memberchk尝试尝试制作' 4'然后' 5'列表的成员,它通过在每种情况下将它们插入到自由变量中而成功完成。

然后当你完成时,关闭它。

答案 1 :(得分:0)

你对这种奇怪的行为是正确的:这是由于length / 2在使用未绑定参数调用时的能力

  

谓词是非确定性的,如果List是部分列表且Int未绑定,则生成长度增加的列表。

示例:

?- length([a,b,c|X],N).
X = [],
N = 3 ;
X = [_G16],
N = 4 ;
X = [_G16, _G19],
N = 5 ;
...

对于您的“应用”代码,这种微小的修正应该足够了。将基本递归子句更改为

catch_all_nth1([], _, _, []).

这是

之前的结果
4 ?- catch_all_nth1([a,b,c,d],2,1,R).
R = [b, d|_G75].

并且在更正之后:

5 ?- catch_all_nth1([a,b,c,d],2,1,R).
R = [b, d].

但我建议改为使用Prolog为我们提供的一些更好的知识方法:例如findall / 3:

?- findall(E, (nth1(I,[a,b,c,d],E), I mod 2 =:= 0), L).
L = [b, d].