我目前正在开始学习Prolog,并努力解决基本问题。
我当前的任务是创建一个使嵌套列表平坦的谓词。我不应该为此使用cut运算符,累加器或->
。
我当前的谓词如下:
my_flatten(X,[X]) :- \+ is_list(X).
my_flatten([],[]).
my_flatten([X|Rest],Flattened) :-
my_flatten(X,Xflat),
my_flatten(Rest,Restflat),
append(Xflat,Restflat,Flattened).
这对于大多数输入而言都可以正常工作。但是,查询my_flatten(abc, [abc])
返回true
而不是false
。
因此,元素1必须是一个列表,但是会干扰规则1,该规则标记了嵌套列表递归的底部。
编辑:
flattenx([],[]).
flattenx([H|T], R) :- flattenx(H, FH), append(FH, FT, R) , flattenx(T, FT).
flattenx([H|T], R) :- \+ flattenx(H, FH), R = [H|FT], flattenx(T, FT).
答案 0 :(得分:2)
我只想证明您的先决条件不能(严格)满足您在 Edit:段落之后发布的解决方案的要求,因为\+
(和{{1 }},即if-then-else)只是语法糖,可以使cut'的使用较少出错。您可以改为在头部使用显式模式来指导子句选择。例如
->
答案 1 :(得分:2)
Carlo和Willem发布的解决方案在要扁平化的列表中存在变量时是不正确的。例如
?- flatten([A,B,C], Flatted).
A = B, B = C, C = Flatted, Flatted = [].
或:
?- flatten_no_cut([A,B,C], Flatted).
ERROR: Out of global-stack.
在存在变量的情况下可以正常工作的解决方案是:
flatten(List, Flatted) :-
flatten(List, [], Flatted).
flatten(Var, Tail, [Var| Tail]) :-
var(Var),
!.
flatten([], Flatted, Flatted) :-
!.
flatten([Head| Tail], List, Flatted) :-
!,
flatten(Tail, List, Aux),
flatten(Head, Aux, Flatted).
flatten(Head, Tail, [Head| Tail]).
通话示例:
?- flatten([A,B,C], Flatted).
Flatted = [A, B, C].
?- flatten([A,[B,1,[a,foo(X)]],C], Flatted).
Flatted = [A, B, 1, a, foo(X), C].
答案 2 :(得分:1)
第一个子句并不是真正必要的:它在列表构造函数中包装不是列表的所有内容。您可能不想要。
本质上,可能发生三件事:
这将导致以下谓词:
php_admin_value
但是,上面的方法不是很优雅,也不是很有效,并且只能在一个方向上工作。我将其保留为练习。