我在 Prolog 的列表中添加元素时遇到问题。我使用这个规则:
add(X, L, [X|L]).
此规则在列表的 Head 中添加一个元素。如果我将一些元素添加到同一个列表中,我会遇到这个问题:
add(a, L, L1),
add(b, L1,L2),
add(c, L2,L3).
L3= [a,b,c]
有没有一种方法可以在不更改变量名称的情况下在列表中添加元素... L1、L2、L3,但将它们添加到单个变量 L 中?
我在 Prolog 的列表中添加元素时遇到问题。我使用这个规则:
add(X, L, [X|L]).
此规则在列表的 Head 中添加一个元素。如果我将一些元素添加到同一个列表中,我会遇到这个问题:
add(a, L, L1),
add(b, L1,L2),
add(c, L2,L3).
L3= [a,b,c]
有没有一种方法可以在不更改变量名称的情况下在列表中添加元素... L1、L2、L3,但将它们添加到单个变量 L 中?
简短的回答是否定的: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 = [].
这是由 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]]
如前所述,简短的回答是否定的。
更长的答案:您不能将项目添加到现有列表(不创建新列表)。您也不能像在其他语言中那样增加变量:您只能创建一个新变量,其值是源变量增加 1。Prolog 数据类型都是不可变的。Prolog 变量,一旦绑定到一个值,就不再是 variable。当执行通过分配回溯时,它们的绑定被撤消。
尽管您不能只添加到与所提出的直接问题相对应的现有列表中,但有些问题可以使用谓词来解决,其解决方案是您要在列表中收集的单独项目,并且您可以使用 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].