Prolog 返回 true/false 而不是变量

Prolog returning true/false instead of variable

我正在研究 Prolog 中非常简单的反向列表示例。

append(A, [], [A]).
append(A, B, [A|B]).

reverse([], ReversedList).
reverse([A,B], ReversedList) :-
  reverse(B, TemporaryList),
  append(A, TemporaryList, ReversedList).

append 正常工作。但是,当我调用 reverse 时,解释器不会响应 append 之类的变量,而是只写 true 或 false。

这是日志:

1 ?- consult('capitolo2'.pl). % file containing the code
2 ?- append(a, [b,c,d], L).
L = [a,b,c,d]. % ok, this works
3 ?- reverse([a,b,c], L).
false. % what? why that's not L = something?

平台是 Windows

上的 SWI-Prolog 7.2

可能还有其他问题,但是

  1. reverse([], ReversedList).
    

    几乎肯定不是您想要的。空列表的反面是空列表,翻译成

    reverse([], []).
    
  2. 此外,

    reverse([A,B], ReversedList)
    

    也可能不是您想要的。它不是一个头A尾B的列表,而是一个2元素列表。

append/3

单元测试了吗?它工作正常吗?您的 append/3 实施不正确。第一条

第一个子句:

append( A , [] , [A]   ). 

简单地从它的第一个参数(不管它可能是什么)创建一个长度为 1 的列表。鉴于此,如果您说:

append( [1,2,3] , [] , X ) .

你会回来:

X = [ [1,2,3] ]

一个长度为 1 的列表,其中包含的唯一项目是原始的第一个参数。第二个条款同样不正确:

append( A , B , [A|B] ).

将第一个参数放在前面——不管它是什么,整个——作为该列表的头部。鉴于此,如果您说的是:

append( [1,2,3] , [a,b,c] , X ) .

你会回来:

X = [ [1,2,3] , a , b , c ] .

一个长度为 4 的列表,其中第一项是原始的第一个参数。

Prolog 是一种描述性语言:您描述解决方案并让引擎解决问题。 append/3 断言列表(append/3 的第三个参数表示第一个参数和第二个参数的串联。

这里是 append/3 的一个实现,为清楚起见进行了简化:

append( []      , RL , RL ) .  % The concatenation of an empty left-hand list and a right hand list is the right hand list.
append( [LH|LT] , RL , CL ) :- % The concatenation of a non-empty left-hand list and a right-hand list is true IF:
  CL = [LH|CT] ,               % - The left-hand head and the concatenation head are the same, AND
  append( LT , RL , CT )       % - recursively, the concatenated tail represents the conconcatenation of the left-hand tail and the right-hand list.
  .                            % Easy!

当您从左侧列表中弹出项目时,它最终会分解为终止的特殊情况。这可以简化为经典实现:

append( []      , RL , RL      ) .
append( [LH|LT] , RL , [LH|CT] ) :- append( LT , RL , CT ) .

reverse/3

同样,您的 reverse/3 实施不正确。你的第一个子句:

reverse([], ReversedList).

pretty much 表示几乎所有内容都与空列表相反。由于您的 ReversedList 变量从未被引用,因此您的 Prolog 实现至少应在此处发出有关单例变量的警告。许多实现使其成为错误。

你的第二个条款:

reverse([A,B], ReversedList) :-
  reverse(B, TemporaryList),
  append(A, TemporaryList, ReversedList).

表示 2 项列表 ([A,B]) 的反向是通过

获得的
  • 反转列表中的第 2 个 (B),并且
  • 将第一项 (A) 添加到那个。

对解决方案的描述不完全正确。你可以试试

reverse( []    , [] ) .  % The empty list is already reversed, what with it being atomic and all.
reverse( [H|T] , R  ) :- % a non-empty list can be reversed by decomposing it into its head and tail, and
  reverse(T,T1) ,        % - reversing the tail, and
  append(T1,H,R) .       % - appending the head to the now-reversed tail.