Prolog返回true/false而不是变量
我正在用Prolog编写一个非常简单的反向列表示例Prolog返回true/false而不是变量,prolog,Prolog,我正在用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之类的变量响应,而是只写
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可能还有其他问题,但是
reverse([], []).
reverse([A,B], ReversedList)
也可能不是你想要的。它不是一个有头a和尾B的列表,而是一个由两个元素组成的列表可能还有其他问题,但是
reverse([], []).
reverse([A,B], ReversedList)
也可能不是你想要的。它不是一个有头a和尾B的列表,而是一个由两个元素组成的列表追加/3
你对它进行了单元测试吗?它工作正常吗?您的append/3
实现不正确。第一条
第一条:
append( A , [] , [A] ).
reverse([], ReversedList).
只需从第一个参数(不管是什么)创建一个长度为1的列表。鉴于此,如果你说:
append( [1,2,3] , [] , X ) .
你会回来的:
X = [ [1,2,3] ]
X = [ [1,2,3] , a , b , c ] .
长度为1的列表,其中唯一包含的项是原始的第一个参数。第二条同样不正确:
append( A , B , [A|B] ).
在第一个参数前面加上前缀-无论它是什么,以及整个作为列表的开头。鉴于此,如果你说:
append( [1,2,3] , [a,b,c] , X ) .
你会回来的:
X = [ [1,2,3] ]
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 ) .
反向/3
同样,您的反向/3
实现是不正确的。您的第一个子句:
append( A , [] , [A] ).
reverse([], ReversedList).
几乎所有内容都是空列表的反面。由于您的ReversedList
变量从未被引用,因此您的Prolog实现至少应该在此处抛出有关单例变量的警告。许多实现都将其视为错误
你的第二条:
reverse([A,B], ReversedList) :-
reverse(B, TemporaryList),
append(A, TemporaryList, ReversedList).
表示两项列表([a,B]
)的反面是通过
- 颠倒列表中的第二项(
),以及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.
追加/3
您是否对其进行了单元测试?它是否正常工作?您的append/3
实现不正确。第一个子句
第一条:
append( A , [] , [A] ).
reverse([], ReversedList).
只需从第一个参数(不管是什么)创建一个长度为1的列表。如果您说:
append( [1,2,3] , [] , X ) .
你会回来的:
X = [ [1,2,3] ]
X = [ [1,2,3] , a , b , c ] .
长度为1的列表,其中唯一包含的项是原始的第一个参数。第二个子句同样不正确:
append( A , B , [A|B] ).
在第一个参数前面加上前缀,无论它是什么,以及整个,作为列表的开头。鉴于此,如果你说:
append( [1,2,3] , [a,b,c] , X ) .
你会回来的:
X = [ [1,2,3] ]
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 ) .
反向/3
同样,您的反向/3
实现是不正确的。您的第一个子句:
append( A , [] , [A] ).
reverse([], ReversedList).
几乎所有内容都是空列表的反面。由于您的ReversedList
变量从未被引用,因此您的Prolog实现至少应该在此处抛出有关单例变量的警告。许多实现都将其视为错误
你的第二条:
reverse([A,B], ReversedList) :-
reverse(B, TemporaryList),
append(A, TemporaryList, ReversedList).
表示两项列表([a,B]
)的反面是通过
- 颠倒列表中的第二项(
),以及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.
结果是一样的:(这就是问题(nr2)。现在它没有返回正确的结果,但这是我的算法中的一个问题结果是一样的:(这就是问题(nr2).现在它没有返回正确的结果,但这是我的算法中的一个问题,这是一个相当非标准的定义,通常
append
被定义用于处理列表,例如append([a,b,c],[x,y,z],L)=>L=[a,b,c,x,y,z]
,这似乎不是问题所在。如果我将append
重命名为my_append
,您也需要重新启动Prolog系统。此外,还有[A,B]
,它可能应该读取[A | B]
等等……只有在第一个参数为空列表的情况下,reverse
规则才会成功([]
)或两元素列表([a,B]
)。由于其他情况不匹配,因此它将使所有其他情况都失败。为什么要实现像append/3
这样的标准谓词?如果有充分的理由这样做