List Prolog中列表的自定义反转

List Prolog中列表的自定义反转,list,nested,prolog,reverse,List,Nested,Prolog,Reverse,我正在尝试编写一个谓词,在Prolog中给出以下列表: [[1,a,b],[2,c,d],[[3,e,f],[4,g,h],[5,i,j]],[6,k,l]] 将生成以下列表: [[6,k,l],[[5,i,j],[4,g,h],[3,e,f]],[2,c,d],[1,a,b]] 如您所见,我希望在最低级别保留元素的顺序,以1,a,b的顺序生成元素,而不是b,a,1 我还想保留列表的深度,也就是说,最初嵌套的列表将以相反的顺序返回 我已使用以下代码实现了所需的顺序,但深度丢失,即列表不再正确

我正在尝试编写一个谓词,在Prolog中给出以下列表:

[[1,a,b],[2,c,d],[[3,e,f],[4,g,h],[5,i,j]],[6,k,l]]
将生成以下列表:

[[6,k,l],[[5,i,j],[4,g,h],[3,e,f]],[2,c,d],[1,a,b]]
如您所见,我希望在最低级别保留元素的顺序,以1,a,b的顺序生成元素,而不是b,a,1

我还想保留列表的深度,也就是说,最初嵌套的列表将以相反的顺序返回

我已使用以下代码实现了所需的顺序,但深度丢失,即列表不再正确嵌套:

accRev([F,S,T],A,R) :- F \= [_|_], S \= [_|_], T \= [_|_], 
                                 accRev([],[[F,S,T]|A],R).
accRev([H|T],A,R) :- accRev(H,[],R1), accRev(T,[],R2), append(R2,R1,R).
accRev([],A,A).
rev(A,B) :- accRev(A,[],B).

如果您能帮我修改代码以保留列表的正确嵌套,我将不胜感激。谢谢

两条建议。首先,这里有一个(
rev_lists/2
)使用了大量SWI-PROLOG内置程序:

rev_lists(L, RL) :-
    forall(member(M, L), is_list(M)), !,
    maplist(rev_lists, L, L0),
    reverse(L0, RL).
rev_lists(L, L).
该方法通过测试列表中的所有元素是否都是列表(
M
);如果是这样,它将递归地(通过
maplist
)应用于所有单独的子列表,否则它将返回相同的列表。这具有所需的效果

其次,这里是
rev_lists/2
,但编写时除了
member/2
(这是常见的)之外,它不依赖内置程序:


这基本上是相同的策略,但使用累加器在每个级别建立反向列表,如果它们完全由列表组成;否则,将返回相同的列表。

谢谢!我使用了第二个变量,并将
is_list(L)
替换为
(L=[];L=[| |])
,就像您对M所做的那样,因为
is_list/1
在GNU Prolog中不可用。非常感谢!哈哈,哇!我很高兴能帮上忙。我将编辑删除
is_list/1
的第二个建议的定义,因为我打算省略任何内置项。干杯
rev_lists(L, RL) :-
    reversible_list(L), !,
    rev_lists(L, [], RL). 
rev_lists(L, L).

rev_lists([], Acc, Acc).
rev_lists([L|Ls], Acc, R) :-
    (   rev_lists(L, RL), !
    ;   RL = L
    ),
    rev_lists(Ls, [RL|Acc], R).

reversible_list(L) :-
    is_a_list(L),
    \+ (
        member(M, L),
        \+ is_a_list(M)
    ).

is_a_list([]).
is_a_list([_|_]).