Prolog - 在同一个列表中添加一些元素

时间:2013-10-18 12:10:12

标签: prolog

我在Prolog的列表中添加元素时遇到问题。我使用这个规则:

add(X, L, [X|L]).

此规则在列表的头部添加一个元素。 如果我要在同一个列表中添加一些元素,我有这个问题:

add(a, L, L1),
add(b, L1,L2),
add(c, L2,L3). 

L3= [a,b,c]

是否有方法在列表中添加元素而不更改变量名称... L1,L2,L3,但是将它们添加到单个变量L?

4 个答案:

答案 0 :(得分:2)

简短的回答是否定的:L必须代表不同的列表,这在Prolog中是错误的。

但你可以实现这样的事情:

add_list([], L, L).
add_list([H|T], L, L1) :- add(H, L2, L1), add_list(T, L, L2).

样本用法:

?- add_list([1,2,3],X,A).
A = [1, 2, 3|X].

?- add_list([1,2,3],X,A), writeln(A-X), add_list([4,5],Y,X).
[1,2,3|_G1188]-_G1188
X = [4, 5|Y],
A = [1, 2, 3, 4, 5|Y].

?- add_list([1,2,3],X,A), writeln(A-X), add_list([4,5],Y,X),Y=[].
[1,2,3|_G1224]-_G1224
X = [4, 5],
A = [1, 2, 3, 4, 5],
Y = [].

答案 1 :(得分:2)

这是由DCG隐含地完成的,将(隐藏的)差异列表参数添加到非终端。 但是如果没有关于你的任务的更多细节,很难暗示任何明智的用法。

SWI-Prolog实际上有一些非常强大的功能,通过非可回溯数据结构来执行通过解决方案链传播的“副作用”任务,但我不确定是否适时提示您这个功能......

编辑在故障驱动循环中更新RBTree的示例:

:- use_module(library(rbtrees)).
:- use_module(library(nb_rbtrees)).

 ordkey :- rb_empty(R),
   forall(member(W, [ls,mkdir,cd,ftp]),
     ( atom_length(W, K),
       (  nb_rb_get_node(R, K, N)
       -> nb_rb_node_value(N, Ws),
          nb_rb_set_node_value(N, [W|Ws])
       ;  nb_rb_insert(R, K, [W])
       )
    )), rb_visit(R, L), writeln(L).

yields

?- ordkey.
[2-[cd,ls],3-[ftp],5-[mkdir]]

答案 2 :(得分:1)

如上所述,简短的答案是否定的。

答案越长:您无法将项目添加到现有列表中(无需创建新列表)。您也不能像在其他语言中那样增加变量:您只能创建一个新变量,其值是源变量,增加1. Prolog数据类型都是不可变。 Prolog变量,一旦绑定到一个值,就不再是变量。当执行通过赋值回溯时,它们的绑定被撤消。

答案 3 :(得分:1)

虽然您不能只添加到现有列表(与所询问的直接问题相对应),但有些类问题可以使用谓词来解决,谓词的解决方案是您要在列表中收集的单独项目,并且您可以使用ISO谓词findall

来收集它们
determin_item( ..., X ) :-
    % Logic which determines X
    % Could be complex with multiple Prolog statements and various conditionals

findall( X, determine_item(..., X), List ).

作为案例的一个简单例子:

foo(1,a).
foo(1,b).
foo(1,c).
foo(2,e).
foo(3,f).

determine_item( X ) :-
    foo(1, X).  % Trivial example to determine X

findall( X, determine_item(X), List ).

将生成:

List = [a,b,c].