List Prolog中谓词的组合

List Prolog中谓词的组合,list,recursion,prolog,reverse,List,Recursion,Prolog,Reverse,我必须做一个谓词reverseeven(List,Reversed),它只在列表有偶数个元素时才会反转列表,如果没有,则返回空列表。 我有一个函数,确定列表中是否有偶数个元素和一个反向函数: evenlength([_,_]). evenlength([_,_|X]):- evenlength(X). reverse([_,_],R). reverse([H|T], R):- reverse(T,ReverseT), append(ReverseT, [H], R). 但是我

我必须做一个谓词
reverseeven(List,Reversed)
,它只在列表有偶数个元素时才会反转列表,如果没有,则返回空列表。 我有一个函数,确定列表中是否有偶数个元素和一个反向函数:

evenlength([_,_]).
evenlength([_,_|X]):-
    evenlength(X).

reverse([_,_],R).
reverse([H|T], R):-
    reverse(T,ReverseT), append(ReverseT, [H], R).
但是我不确定如何组合这两个谓词。

你不能“组合”谓词,但你可以在两个(或更多)谓词之间进行逻辑连接,只有当两个谓词都成功时才会成功:

reverseEven(List, Reversed) :- 
      evenlength(List),            % This must succeed 
      reverse(List, Reversed).     % and this one in order this case to succeed

reverseEven(_, []).                % this will succeed otherwise
以上不是最有效的实现(例如,在检查偶数长度后,可以使用cut
操作符)。但它表明了这个想法

更新 顺便说一下,您的
反向
谓词应该如下所示:

reverse([],[]).    % Empty list is a reverse of empty list
reverse([H|T], R):-
    reverse(T,ReverseT), append(ReverseT, [H], R).    
更新2谢谢@潜伏者。上述代码将产生两个答案。第一个是正确的。如果我们要求Prolog进一步搜索,它将找到另一个答案,即空列表,因为第二个子句总是正确的。为了解决这个问题,我们可以显式地检查列表的长度是否使用了否定运算符,或者我发现更优雅的方法是为空列表添加另一个子句,对于非偶数检查,只需使用现有的
evenlength
和具有额外元素的列表:

reverseEven([], []).  
reverseEven(List, Reversed) :- 
    evenlength(List),            % This must succeed 
    reverse(List, Reversed).     % and this one in order this case to succeed

reverseEven([H|T], []) :- 
    evenlength([H|[H|T]]).

不幸的是,这段代码产生了两种解决方案
reverseEven([a,b],R)
。一个是正确的(
R=[b,a]
),另一个是不正确的,
R=[]
@潜伏者你是对的,谢谢。将更新答案,尽管这不是问题的重点。我同意这不是重点,但在提供解决方案时,最好是正确的解决方案,或者明确说明它不正确或不完整,并将其作为OP找到完整解决方案的练习。:)