所以我有一个程序,它有一个谓词,用给定的新元素替换列表中某个元素的第一次出现,并产生一个新列表。我是这样做的:
changeFst(OldE,[OldE|T],NewE,[NewE|T]):-!.
changeFst(OldE,[_|T],NewE,_):- changeFst(OldE,T,NewE,_),!.
例如如果你给(2(1、2、3、4、2],10 X) 应该还给你 X =[1、10、3、4、2)
现在我正在制作更改最后出现的部分(在示例中它将返回X=[1,2,3,4,10])。这是我的代码:
changeLast(OldE,OldL,NewE,NewL):-
reverse(OldE,X),
changeFst(OldE,X,NewE,NewL),
!.
所以这实际上很好但问题是它返回的是反向的列表(在上面的例子中它返回的是[10,4,3,2,1]而不是[1,2,3,4,10])
我怎样才能再次反转以正确显示我的答案?
你对changeFst/4
的定义在许多方面是不正确的,比如changeFst(o,[o,o],n,[m,y,s,t,e,r,y]).
成功了,但显然它应该失败。原因是你对cuts的用法不正确。如果您想学习Prolog,请首先坚持学习纯声明性子集。这意味着没有伤口,也没有副作用。
这是一个不依赖于剪切的定义:
changeFst(Old,[Old|Olds],New,[New|Olds]).
changeFst(Old,[E|Olds],New,[E|News]):-
dif(Old, E),
changeFst(Old,Olds,New,News).
这种纯关系的一个优点是,我们可以使用最一般的查询来查看我们得到的答案:
?- changeFst(Old, Olds, New, News).
Olds = [Old|_A], News = [New|_A]
; Olds = [_A,Old|_B], News = [_A,New|_B], dif(Old,_A)
; Olds = [_A,_B,Old|_C], News = [_A,_B,New|_C],
dif(Old,_A), dif(Old,_B)
; Olds = [_A,_B,_C,Old|_D], News = [_A,_B,_C,New|_D],
dif(Old,_A), dif(Old,_B), dif(Old,_C)
; ... .
你注意到答案总是包含Olds
a 部分列表吗?如:第一个答案中的Olds = [Old|_A]
。这可能有点太笼统了,毕竟这意味着现在甚至非列表也被接受了:
?- changeFst(o,[o|nonlist], New, News).
News = [New|nonlist]
; false.
所以你可能想确保Olds
和News
总是列表。
但是我想说明的是,我想告诉你的是,在纯关系中,你可以看到很多东西,这些东西是被截断的程序无法直接显示的。
如果我们在它:如何处理空列表?当前版本表明changeFst/4
应该失败。不确定你想要什么,但如果你想要它成功,首先添加一个事实changeFst(_,[],_,[]).
。
如果您的Prolog不支持dif/2
(Prolog -dif),请参阅此答案。
按照@false:
的建议,使用if_/3
和(=)/3
来保持纯净和高效。changeFst(Old,Olds,New,News) :-
list_change_first_(Olds,News,Old,New).
list_change_first_([],[],_,_).
list_change_first_([X|Xs],[Y|Ys],Old,New) :-
if_(X = Old, (Y = New, Ys = Xs),
(Y = X, list_change_first_(Xs,Ys,Old,New))).
示例查询:?- changeFst(2,[1,2,3,4,2],10,Xs).
Xs = [1,10,3,4,2]. % succeeds deterministically
?- changeFst(o,[o,o],n,[m,y,s,t,e,r,y]).
false. % expected result
?- changeFst(Old,Olds,New,News).
Olds = [], News = [] ;
Olds = [Old|_A], News = [New|_A] ;
Olds = [_A], News = [_A], dif(_A,Old) ;
Olds = [_A,Old|_B], News = [_A,New|_B], dif(_A,Old) ;
Olds = [_A,_B], News = [_A,_B], dif(_A,Old), dif(_B,Old) ;
Olds = [_A,_B,Old|_C], News = [_A,_B,New|_C], dif(_A,Old), dif(_B,Old) % and so on...