2

I tried this

 fun([],[]).
 fun([A|_],B) :- number(A), B is A +1,!.
 fun([H|T],R) :- fun(T,R).

I know it's wrong, could you help me? Thanks

Guy Coder
  • 24,501
  • 8
  • 71
  • 136
Pierminator
  • 93
  • 2
  • 12

2 Answers2

3

For seeing that your program cannot work, you can either try it out:

?- fun([1],L).
   L = 2.
?- fun([1],[]).
   true.
?- fun([X],L).
   L = [].

So this shows clearly non-relational behavior: In the first query we ask for an L and get L = 2 as an answer, but then we ask about [] being an answer ; and the system accepts that too. Clearly, your definition cannot be a relation. The culprit is certainly the cut.

Apart from that, there are also other ways to see problems. It suffices to look at one rule alone. The first rules (fun([A|_],B) :- number(A), B is A +1,!.) says that the second argument must be an integer (in certain situations). But it should be a list. The second rule (fun([H|T],R) :- fun(T,R).) says that any element can be skipped. Clearly that cannot be part of a meaningful definition.

The most concise way would use the higher-order predicate maplist/3 and lambda expressions as defined in library(lambda). Written this way, an intermediary predicate is usually not used.

fun(Xs, Ys) :-
   maplist(\X^Y^(Y is X+1), Xs, Ys).

The next version avoids lambdas and uses a concrete definition instead:

msucc(X, Y) :-
   Y is X+1.

fun(Xs, Ys) :-
   maplist(msucc, Xs, Ys).

In fact, there is a predefined predicate succ/2 which is present in many Prologs and is part of the Prolog prologue.

fun(Xs, Ys) :-
   maplist(msucc, Xs, Ys).

The most "pedestrian" way of defining it would be directly with a predicate definition:

fun([], []).
fun([X|Xs], [Y|Ys]) :-
   Y is X+1,
   fun(Xs, Ys).

Which one do you prefer?

For more about the maplist-family: Prolog map procedure that applies predicate to list elements


If you want to learn Prolog, stick to to pure relations first. Avoid the cut. Avoid side effects like write. Avoid even (is)/2. Use and later . Study termination and non-termination , and .

false
  • 10,264
  • 13
  • 101
  • 209
0

The problem is that you're not consistent and you're not finishing the recursion.

With your code, something like this is true:

fun([a,b,c],X) .

and will result in X having the value [], but

fun([a,1,b],X) .

will result in X having the value 2.

If you want to find the first number in the list and increment it by one, something like this will do:

fun([X|Xs],Y) :- number(X) , ! , Y is X+1 .
fun([_|Xs],Y) :- fun(Xs,Y) .

If you want to increment each number in the list, then try something like this:

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.

You should not that this could be more concisely states as

fun( [] , [] ) :-
fun( [X|Xs] , [Y|Ys] ) :-
  increment(X,Y) ,
  fun( Xs , Ys )
  .

increment(X,Y) :- number(X) , ! , Y is X+1 .
increment(X,X) .

Or, more concisely yet

fun( [] , [] ) .
fun( [X|Xs] , [Y|Ys] ) :-
  ( number(X) -> Y is X+1 ; Y = X ) ,
  fun(Xs,Ys).

The A -> B ; C construct is the implication operator.

Nicholas Carey
  • 71,308
  • 16
  • 93
  • 135