我试过这个
fun([],[]).
fun([A|_],B) :- number(A), B is A +1,!.
fun([H|T],R) :- fun(T,R).
我知道这是错的,你能帮助我吗?感谢
答案 0 :(得分:3)
要查看您的程序无法运行,您可以尝试一下:
?- fun([1],L).
L = 2.
?- fun([1],[]).
true.
?- fun([X],L).
L = [].
因此,这显示了非关系行为:在第一个查询中,我们要求L
并获取L = 2
作为答案,但之后我们会询问[]
是否为答案;并且系统也接受了。显然,你的定义不能成为一种关系。罪魁祸首当然是削减。
除此之外,还有其他方法可以看到问题。仅仅看一个规则就足够了。第一个规则(fun([A|_],B) :- number(A), B is A +1,!.
)表示第二个参数必须是整数(在某些情况下)。但它应该是一个清单。第二条规则(fun([H|T],R) :- fun(T,R).
)表示可以跳过任何元素。显然,这不能成为有意义定义的一部分。
最简洁的方法是使用maplist/3
中定义的高阶谓词library(lambda)和lambda表达式。以这种方式编写,通常不使用中间谓词。
fun(Xs, Ys) :-
maplist(\X^Y^(Y is X+1), Xs, Ys).
下一个版本避免使用lambda,而是使用具体的定义:
msucc(X, Y) :-
Y is X+1.
fun(Xs, Ys) :-
maplist(msucc, Xs, Ys).
事实上,预定义谓词succ/2
存在于许多Prolog中,并且part of the Prolog prologue。
fun(Xs, Ys) :-
maplist(msucc, Xs, Ys).
最多"行人"定义它的方式将直接与谓词定义:
fun([], []).
fun([X|Xs], [Y|Ys]) :-
Y is X+1,
fun(Xs, Ys).
您更喜欢哪一个?
有关maplist-family的更多信息:Prolog map procedure that applies predicate to list elements
如果你想学习Prolog,首先要坚持纯粹的关系。避免切割。避免像write
这样的副作用。甚至避免(is)/2
。使用successor-arithmetics及更高版本clpfd。学习终止和非终止failure-slice和dcg。
答案 1 :(得分:0)
问题在于你不一致而且你没有完成递归。
使用您的代码,这样的事情是真的:
fun([a,b,c],X) .
将导致X具有值[]
,但
fun([a,1,b],X) .
将导致X具有值2
。
如果你想在列表中找到第一个数字并将其递增1,那么这样的事情就会出现:
fun([X|Xs],Y) :- number(X) , ! , Y is X+1 .
fun([_|Xs],Y) :- fun(Xs,Y) .
如果你想增加列表中的每个数字,那么尝试这样的事情:
fun( [] , [] ) . % if the source list is exhausted, we're done.
fun( [X|Xs] , [Y|Ys] ) :- % otherwise,
number(X) , % - if X is a number,
Y is A+1 % - we increment it to get Y
fun( Xs , Ys ) . % - and recurse down on the tails of the respective lists
fun( [X|Xs] , [X|Ys] ) :- % otherwise, add X to the result list
\+ number(X) , % - assuming X is not a number,
fun(Xs,Ys) . % - and recurse down.
你不应该认为这可以更简洁地说明
fun( [] , [] ) :-
fun( [X|Xs] , [Y|Ys] ) :-
increment(X,Y) ,
fun( Xs , Ys )
.
increment(X,Y) :- number(X) , ! , Y is X+1 .
increment(X,X) .
或者,更简洁
fun( [] , [] ) .
fun( [X|Xs] , [Y|Ys] ) :-
( number(X) -> Y is X+1 ; Y = X ) ,
fun(Xs,Ys).
A -> B ; C
构造是implication operator。