Prolog reverse lookup and input validation at the same time - prolog

I have started learning prolog recently and even though it is refreshing to move away from functional programming, things still seem very foreign. I having trouble understanding how I can write a predicate that checks whether its argument adhere to a certain set of rules and also at the same time if given a variable will set it to the possible values that satisfy those rules.
I was trying to solve the circular table seating problem where you define a set of conditions for people to sit next to each other. So the knowledge base contains 10 individuals with the languages they speak and the goal is to seat them in a way such that two people sitting next to each other must speak the same language.
I defined a predicate speaks_same(X, Y) which returns true if both individuals X and Y speak the same language. Now the goal is to write a function table_seating such that table_seating([mark, carl, emily, kevin, oliver]) returns true if each two people sitting next to each other in the list speak a common language. Of course for this to happen each person must speak more than one language. And also table_seating(L). would produce the possible table seatings that satisfy the condition.
The way I see it is I can either write a predicate that checks if a previously defined list satisfies the rules or one the builds a list according to these rules. I don't understand how I can do both with one function.
Any help would be really appreciated, thanks!

I don't understand how I can do both with one function.
Yes, at first this seems odd, but then once you get the hang of it, you miss it in other languages.
The word you want to remember when referencing this is: mode
Also see Mercury Modes reference for more detail related to the Mercury programming language.
In Prolog an argument can be an input, and output, or both used as an input or output depending upon how it is called.
In Type, mode and determinism declaration headers at the bottom is listed 4 examples.
length(+List:list, -Length:int) is det.
length(?List:list, -Length:int) is nondet.
length(?List:list, +Length:int) is det.
True if List is a list of length Length.
and the definition of length/2 shows
length(?List, ?Int)
meaning
that for the List argument, the list can be bound or unbound, and
that for the Int argument, the value can be bound or unbound.
So for the two arguments with two options there are four ways to use length/2
Here they are listed again but in actual usage.
1.
length(+List:list, -Length:int) is det.
in this case List is bound and Length is unbound and always gives one answer.
?- length([1,2,3],N).
N = 3.
2.
length(?List:list, -Length:int) is nondet.
in this case List is unbound and Length is unbound and can return any number of answers.
?- length(List,N).
List = [],
N = 0 ;
List = [_5362],
N = 1 ;
List = [_5362, _5368],
N = 2 ;
List = [_5362, _5368, _5374],
N = 3 ;
List = [_5362, _5368, _5374, _5380],
N = 4 ;
List = [_5362, _5368, _5374, _5380, _5386],
N = 5
...
3.
length(?List:list, +Length:int) is det.
in this case List is unbound and Length is bound and always gives one answer.
?- length(List,4).
List = [_5332, _5338, _5344, _5350].
4.
True if List is a list of length Length.
in this case List is bound and Length is bound and always acts as predicate to return either true or false.
?- length([1,2,3],3).
true.
?- length([1,2,3],5).
false.
So how is this possible?
Prolog uses syntactic unification (↦) and NOT assignment (=).
If we look at the source code for length/2 using listing/1 we get
?- listing(length/2).
system:length(B, A) :-
var(A), !,
'$skip_list'(D, B, C),
( C==[]
-> A=D
; var(C)
-> C\==A,
'$length3'(C, A, D)
; throw(error(type_error(list, B), context(length/2, _)))
).
system:length(B, A) :-
integer(A),
A>=0, !,
'$skip_list'(D, B, C),
( C==[]
-> A=D
; var(C)
-> E is A-D,
'$length'(C, E)
; throw(error(type_error(list, B), context(length/2, _)))
).
system:length(_, A) :-
integer(A), !,
throw(error(domain_error(not_less_than_zero, A),
context(length/2, _))).
system:length(_, A) :-
throw(error(type_error(integer, A), context(length/2, _))).
which is too much detail but does do all 4 modes correctly.
To make it easier to understand we will use this version, but it doesn't support 1 of the modes correctly but it does do more than one mode so it works good enough to demonstrate.
length_2([] , 0 ).
length_2([_|Xs] , L ) :-
length_2(Xs,N),
L is N+1 .
Now to see the unification in action we will use the trace feature of SWI-Prolog and to enable all of the ports for the box model use visible/1 and so as not to stop it when running use leash/1.
?- visible(+all),leash(-all).
?- trace.
1.
[trace] ?- length_2([1,2,3],N).
Call: (8) length_2([1, 2, 3], _2352)
Unify: (8) length_2([1, 2, 3], _2352)
Call: (9) length_2([2, 3], _2580)
Unify: (9) length_2([2, 3], _2580)
Call: (10) length_2([3], _2580)
Unify: (10) length_2([3], _2580)
Call: (11) length_2([], _2580)
Unify: (11) length_2([], 0)
Exit: (11) length_2([], 0)
Call: (11) _2584 is 0+1
Exit: (11) 1 is 0+1
Exit: (10) length_2([3], 1)
Call: (10) _2590 is 1+1
Exit: (10) 2 is 1+1
Exit: (9) length_2([2, 3], 2)
Call: (9) _2352 is 2+1
Exit: (9) 3 is 2+1
Exit: (8) length_2([1, 2, 3], 3)
N = 3.
2.
[trace] ?- length_2(List,N).
Call: (8) length_2(_2296, _2298)
Unify: (8) length_2([], 0)
Exit: (8) length_2([], 0)
List = [],
N = 0 ;
Redo: (8) length_2(_2296, _2298)
Unify: (8) length_2([_2528|_2530], _2298)
Call: (9) length_2(_2530, _2550)
Unify: (9) length_2([], 0)
Exit: (9) length_2([], 0)
Call: (9) _2298 is 0+1
Exit: (9) 1 is 0+1
Exit: (8) length_2([_2528], 1)
List = [_2528],
N = 1 ;
Redo: (9) length_2(_2530, _2550)
Unify: (9) length_2([_2534|_2536], _2556)
Call: (10) length_2(_2536, _2556)
Unify: (10) length_2([], 0)
Exit: (10) length_2([], 0)
Call: (10) _2560 is 0+1
Exit: (10) 1 is 0+1
Exit: (9) length_2([_2534], 1)
Call: (9) _2298 is 1+1
Exit: (9) 2 is 1+1
Exit: (8) length_2([_2528, _2534], 2)
List = [_2528, _2534],
N = 2 ;
Redo: (10) length_2(_2536, _2556)
Unify: (10) length_2([_2540|_2542], _2562)
Call: (11) length_2(_2542, _2562)
Unify: (11) length_2([], 0)
Exit: (11) length_2([], 0)
Call: (11) _2566 is 0+1
Exit: (11) 1 is 0+1
Exit: (10) length_2([_2540], 1)
Call: (10) _2572 is 1+1
Exit: (10) 2 is 1+1
Exit: (9) length_2([_2534, _2540], 2)
Call: (9) _2298 is 2+1
Exit: (9) 3 is 2+1
Exit: (8) length_2([_2528, _2534, _2540], 3)
List = [_2528, _2534, _2540],
N = 3
3.
[trace] ?- length_2(List,3).
Call: (8) length_2(_5534, 3)
Unify: (8) length_2([_5724|_5726], 3)
Call: (9) length_2(_5726, _5746)
Unify: (9) length_2([], 0)
Exit: (9) length_2([], 0)
Call: (9) 3 is 0+1
Fail: (9) 3 is 0+1
Redo: (9) length_2(_5726, _5746)
Unify: (9) length_2([_5730|_5732], _5752)
Call: (10) length_2(_5732, _5752)
Unify: (10) length_2([], 0)
Exit: (10) length_2([], 0)
Call: (10) _5756 is 0+1
Exit: (10) 1 is 0+1
Exit: (9) length_2([_5730], 1)
Call: (9) 3 is 1+1
Fail: (9) 3 is 1+1
Redo: (10) length_2(_5732, _5752)
Unify: (10) length_2([_5736|_5738], _5758)
Call: (11) length_2(_5738, _5758)
Unify: (11) length_2([], 0)
Exit: (11) length_2([], 0)
Call: (11) _5762 is 0+1
Exit: (11) 1 is 0+1
Exit: (10) length_2([_5736], 1)
Call: (10) _5768 is 1+1
Exit: (10) 2 is 1+1
Exit: (9) length_2([_5730, _5736], 2)
Call: (9) 3 is 2+1
Exit: (9) 3 is 2+1
Exit: (8) length_2([_5724, _5730, _5736], 3)
List = [_5724, _5730, _5736]
Action (h for help) ? abort
% Execution Aborted
4.
[trace] ?- length_2([1,2,3],3).
Call: (8) length_2([1, 2, 3], 3)
Unify: (8) length_2([1, 2, 3], 3)
Call: (9) length_2([2, 3], _2058)
Unify: (9) length_2([2, 3], _2058)
Call: (10) length_2([3], _2058)
Unify: (10) length_2([3], _2058)
Call: (11) length_2([], _2058)
Unify: (11) length_2([], 0)
Exit: (11) length_2([], 0)
Call: (11) _2062 is 0+1
Exit: (11) 1 is 0+1
Exit: (10) length_2([3], 1)
Call: (10) _2068 is 1+1
Exit: (10) 2 is 1+1
Exit: (9) length_2([2, 3], 2)
Call: (9) 3 is 2+1
Exit: (9) 3 is 2+1
Exit: (8) length_2([1, 2, 3], 3)
true.
[trace] ?- length_2([1,2,3],5).
Call: (8) length_2([1, 2, 3], 5)
Unify: (8) length_2([1, 2, 3], 5)
Call: (9) length_2([2, 3], _2442)
Unify: (9) length_2([2, 3], _2442)
Call: (10) length_2([3], _2442)
Unify: (10) length_2([3], _2442)
Call: (11) length_2([], _2442)
Unify: (11) length_2([], 0)
Exit: (11) length_2([], 0)
Call: (11) _2446 is 0+1
Exit: (11) 1 is 0+1
Exit: (10) length_2([3], 1)
Call: (10) _2452 is 1+1
Exit: (10) 2 is 1+1
Exit: (9) length_2([2, 3], 2)
Call: (9) 5 is 2+1
Fail: (9) 5 is 2+1
Fail: (8) length_2([1, 2, 3], 5)
false.
and to turn the trace off
[trace] ?- notrace.
true.
[debug] ?- nodebug.
true.
I won't go through each of the lines in the trace output, but if you understand syntactic unification and can follow the trace, after working through the examples given you will see how variables in Prolog are unified resulting in different modes when compared to imperative programming.
Remember that variables are only bound once in Prolog, and never reassigned, and that the numbers on the left in the trace in parenthesis, e.g. (10), are the stack level, so when a call is made to a predicate again, a new set of variables are made available, and while it may seem the are being reassigned a value, it is actually another variable in the stack, just in a different stack frame.
As an aside when learning Prolog one piece of advise I give is that it is easier to learn if you set aside what you know about imperative and functional programming, except for maybe recursion, and start from the ground up with unification and then backward chaining.
If you can read OCaml, here is a simplified version of unification and backward chaining. Note that this is not a Prolog as it does not have list or the cut operator but if you can understand it, then the ways of unification and backward chaining become apparent.
I have to add that I am not totally satisfied with my answer as I know you are a beginner and this answer is to much information to digest and requires a lot of work on your part to work through the 4 trace examples. However it does answer the question and gives a practical example with more than enough meat on the bone. I am working on trying to think of a better example which would include logical purity and that demonstrates that not only unification but relationships are key to how multiple modes can be accomplishes in one predicate. Be glad I didn't use general relativity as paraphrased by the relativist John Archibald Wheeler, spacetime tells matter how to move; matter tells spacetime how to curve.

I have been doing Prolog for a few years and I feel like my comfort with and understanding of different instantiation patterns has come in several discrete steps. The first significant hurdle is of course recursion, which is all you really need to get your head around for this problem. Basically, you know that your table assignment for two people is correct if they speak the same language, so this is your base case:
table_seating([X,Y]) :- speaksSame(X, Y).
So, what if you add a third person to the mix? You'd do something like this:
% for exposition only; do not include this clause
table_seating([A,X,Y]) :- speaksSame(A,X), speaksSame(X, Y).
Now hopefully you notice that your new work is speaksSame(A,X) but your old work has remained the same. Let's just worry about the new person and trust that we could have handled it for the remainder of the list.
table_seating([X,Y,Z|Rest]) :-
speaksSame(X, Y),
table_seating([Y,Z|Rest]).
What we're doing here is saying, assume we have at least three items in the list. Then if the first two speak the same language, and the next two plus the rest can be seated, then they can all be seated. You can always take a correctly-seated table and add a person to the front of the table, if they speak the same language as the person currently at the front of the table.
Recursion almost always has this flavor: how can I set up the minimal correct situation, the base case, and then, how can I add one more thing to that situation correctly?
Now what's interesting is that if you supply a list of some length to this predicate, it will "just work" and produce solutions of that length. Try it like so:
?- length(L, 6), table_seating(L).
You will probably get solutions (I assume speaksSame/2 will generate solutions). This is because all Prolog knows about these variables, it knows about because of your speaksSame/2 predicate. So as long as you use predicates that have many instantiation patterns in your predicates and don't force assignments to things or order things strangely, often your predicates will inherit these modes. This is a reason I recommend people use succ/2 instead of N is N0 + 1 or N0 is N - 1, because succ/2 defines a relationship between two numbers rather than performing some arithmetic (clpfd takes this idea much, much further).

In Prolog, generation and validation are one and the same thing: the table_seating predicate does both in any case, unless you deliberately produce non-relational code. i.e. the statement table_seating(X) says “X is a table seating”. if, then, X is bound and is a valid table seating, the “call” will succeed. If X is bound and invalid, the call will fail, if unbound, it will be filled with a valid seating and the call will pass.
i.e. Prolog makes sure that truth always wins. And the “making sure” is the execution/evaluation (which is implemented as a potentially failing search).
So the predicate merely needs to express what it means for something to be a table seating.

Related

Prolog how to add element in a list if is in a list

I m trying to do a list member(member/2) with my own predicate.
starting this example
?-app([a,r,t],[t,s,m,n,a],L3).
L3=[a,t]
I tried to do similar exercises so I did this with prolog:
app([],_,[]).
app([H|T],[H1,T1],[H|L1]):- H is H1, L1 is H,! ,app(T,T1,L1).
app([_H|T],L,L2):- app(T,L,L2).
and all working regular, but the value in a list will be overwritten during the execution, in fact, the trace is :
trace, app([3,2],[3,5],X).
Call: (9) app([3, 2], [3, 5], _7426) ? creep
Call: (10) 3 is 3 ? creep
Exit: (10) 3 is 3 ? creep
Call: (10) _7736 is 3 ? creep
Exit: (10) 3 is 3 ? creep
Call: (10) app([2], 5, 3) ? creep
Call: (11) app([], 5, 3) ? creep
Fail: (11) app([], 5, 3) ? creep
Fail: (10) app([2], 5, 3) ? creep
Fail: (9) app([3, 2], [3, 5], _7426) ? creep
false.
I tried to make a modify on the base case in this way:
app([],_,_N).
but the output is every wrong:
trace, app([3,2],[3,5],X).
Call: (9) app([3, 2], [3, 5], _7426) ? creep
Call: (10) 3 is 3 ? creep
Exit: (10) 3 is 3 ? creep
Call: (10) _7736 is 3 ? creep
Exit: (10) 3 is 3 ? creep
Call: (10) app([2], 5, 3) ? creep
Call: (11) app([], 5, 3) ? creep
Exit: (11) app([], 5, 3) ? creep
Exit: (10) app([2], 5, 3) ? creep
Exit: (9) app([3, 2], [3, 5], [3|3]) ? creep
X = [3|3].
where I m wrong?
I think you're trying to do a sublist/2 predicate:
%! sublist(Sub, List)
% is true if Sub is a list that occurs in
% some position in List
sublist(Sub, List) :-
% first partition off some tail of the list
append(_Prefix, Tail, List),
% then get some prefix of the tail, this is a sublist
append(Sub, _TailTail, Tail).
There's more ways to do this, but I think append/3 is simple to
understand. This is a different problem from member/2, which is finding elements in a list, here our problem is to carve up a list into chunks, hence the very different implementation than you see in member/2. You'll often find in Prolog the first step to a solution is to define the problem well. Good luck in your Prolog learning.

Prolog recursion in sum of n natural numbers

I am having trouble to understand how value of Z is constantly changing. The specific step has been indicated in the stack trace output.
Here is the code I am using for finding sum of N natural numbers -
sum1(1,1).
sum1(N, Sum) :-
Next is N-1,
sum1(Next, Z),
Sum is Z + N.
Here is the stack trace -
?- sum1(3,_).
Call: (8) sum1(3, _2668) ? creep
Call: (9) _2860 is 3+ -1 ? creep
Exit: (9) 2 is 3+ -1 ? creep
Call: (9) sum1(2, _2862) ? creep
Call: (10) _2866 is 2+ -1 ? creep
Exit: (10) 1 is 2+ -1 ? creep
Call: (10) sum1(1, _2868) ? creep
Exit: (10) sum1(1, 1) ? creep
Call: (10) _2872 is 1+2 ? creep
Exit: (10) 3 is 1+2 ? creep
Exit: (9) sum1(2, 3) ? creep **%How is Z assigned value 3 ?**
Call: (9) _2668 is 3+3 ? creep
Exit: (9) 6 is 3+3 ? EOF: exit
Thanks in advance!
It is not "changing"; each proof of sum1 gets its own versions of N, Sum, Next and Z. This is why, in the stack trace, each gets a different generated name (i.e. _2860), so Prolog can tell them apart.
As to your specific question, 2 lines above the line you ask about, that particular Sum is _2872; so proving _2872 is 1+2 requires _2872 to be 3. And this Sum is matched to the previous call sum(1, _2868), where _2868 was that sum1's Z (as you can see from 2 lines above that).

PROLOG: addOne predicate, what happens when temp. variable hits the base clause, how does Prolog call values?

I need some help with understanding the following Prolog source code:
addone([],[]).
addone([H|T],[H1|T1]):-H1 is H + 1, addone(T,T1).
This code, takes a given list and therefore prints out another one which has +1 added to each argument of it.
I don't understand how exactly this work, if I trace it:
[trace] 69 ?- addone([1,2,3],X).
Call: (6) addone([1, 2, 3], _G1196) ? creep
Call: (7) _G1273 is 1+1 ? creep
Exit: (7) 2 is 1+1 ? creep
Call: (7) addone([2, 3], _G1274) ? creep
Call: (8) _G1279 is 2+1 ? creep
Exit: (8) 3 is 2+1 ? creep
Call: (8) addone([3], _G1280) ? creep
Call: (9) _G1285 is 3+1 ? creep
Exit: (9) 4 is 3+1 ? creep
Call: (9) addone([], _G1286) ? creep
Exit: (9) addone([], []) ? creep
Exit: (8) addone([3], [4]) ? creep
Exit: (7) addone([2, 3], [3, 4]) ? creep
Exit: (6) addone([1, 2, 3], [2, 3, 4]) ? creep
X = [2, 3, 4].
I get to the point:
Call: (9) addone([], _G1286) ? creep
Exit: (9) addone([], []) ? creep
From here I don't understand how when I reach the base clause Prolog recalls its saved values?
Can you please explain me how this thing works, what is the logic behind it?
Thank you in advance, Petar!
I guess the answer you might be looking for is:
When Prolog sees a predicate defined like this (most simple example):
foo([]).
foo([_|_]).
This predicate will now be deterministic on proper lists. In other words, it will succeed exactly once. This is because Prolog can recognize by loooking at the two clauses that they are mutually exclusive. In other words, for any non-empty list the second clause only can apply, and for an empty list the first clause only can apply.
In other words, for a proper list of length Len, after Len calls of the second clause, a call of the first clause will follow. At that point it succeeds, and all recursive calls (which were tail recursive) will succeed, in reverse order of how they were called.
In your example, before the recursive call is even made, a value is calculated and ready to be used when the call succeeds.
One thing here is that when you call with it a second argument a variable, you will keep on unifying this variable with a head of a list (the number you calculated) and a free tail [H1|T1], which you pass to the recursive call addone(T, T1). Only when the first argument is the empty list, will the second argument also be unified with an empty list: addone([], []). Now, on the return from the recursive calls, the list of values (growing from behind) will be unified with the free tails [4|[]], [3|[4|[]]] [2|[3|[4|[]]]], eventually building the final list in the second argument.

Some doubts about declarative meaning of a program that prints a list of lists in Prolog

Write a rule that take a list whose elements are themselves lists and
print on each line the elements of internals list:
Example:
?- printList[[1,a],[2,b]]).
1 a
2 b
The solution it the following one:
/* BASE CASE: The list is empty, so there is nothing to print */
printList([]).
printList([P|R]):- printList(P),
!,
nl,
printList(R).
printList([X|R]):- write(X),
!,
printList(R).
I have the printList rule that reaches the base case when the list is empty and in this case there is nothing to print.
If I am not in the base case (the list is not empty) it calls the second rule printList([P|R]) and now I have my first doubt:
The element P is a list because Prolog automatically handles an internal list as an element?
So, If I have something like:
[[1,a],[2,b],[3,c],[4,d]] I have that Prolog automatically match in this way:
P = [1,a] (the first list as the head element)
R = [[2,b],[3,c],[4,d]] (the other 3 list are the element of a tail list)
And then the program calls the printList predicate on the head element (the first list) and this version of the rule writes all the elements in the current list.
Is this right this interpretation?
Now I have some doubts about about the trace of this program, for example if I execute this statement I obtain the following trace:
[trace] ?- printList([[1,a], [2,b]]).
Call: (6) printList([[1, a], [2, b]]) ? creep
Call: (7) printList([1, a]) ? creep
Call: (8) printList(1) ? creep
Fail: (8) printList(1) ? creep
Redo: (7) printList([1, a]) ? creep
Call: (8) write(1) ? creep
1
Exit: (8) write(1) ? creep
Call: (8) printList([a]) ? creep
Call: (9) printList(a) ? creep
Fail: (9) printList(a) ? creep
Redo: (8) printList([a]) ? creep
Call: (9) write(a) ? creep
a
Exit: (9) write(a) ? creep
Call: (9) printList([]) ? creep
Exit: (9) printList([]) ? creep
Exit: (8) printList([a]) ? creep
Exit: (7) printList([1, a]) ? creep
Call: (7) nl ? creep
Exit: (7) nl ? creep
Call: (7) printList([[2, b]]) ? creep
Call: (8) printList([2, b]) ? creep
Call: (9) printList(2) ? creep
Fail: (9) printList(2) ? creep
Redo: (8) printList([2, b]) ? creep
Call: (9) write(2) ? creep
2
Exit: (9) write(2) ? creep
Call: (9) printList([b]) ? creep
Call: (10) printList(b) ? creep
Fail: (10) printList(b) ? creep
Redo: (9) printList([b]) ? creep
Call: (10) write(b) ? creep
b
Exit: (10) write(b) ? creep
Call: (10) printList([]) ? creep
Exit: (10) printList([]) ? creep
Exit: (9) printList([b]) ? creep
Exit: (8) printList([2, b]) ? creep
Call: (8) nl ? creep
Exit: (8) nl ? creep
Call: (8) printList([]) ? creep
Exit: (8) printList([]) ? creep
Exit: (7) printList([[2, b]]) ? creep
Exit: (6) printList([[1, a], [2, b]]) ? creep
true.
This is quite clear for me (I think that my previous reasoning is right) but I am not understanding why whenever it reaches an element in an internal list it calls the printList relation on it (that is a simple element and not a list), for example here:
Call: (8) printList(1) ? creep
Fail: (8) printList(1) ? creep
the program had considered the first list of the original list and then, into it to have to print its first element, why call the printList relation on this simple element
Is it because this simple element may in turn be internal lists?
Something like:
[[[1.1,a1,a2],[1.2,b1,b2]], [2,b]] (in which I have a list that contains 2 lists and the first element it is a list that contains 2 lists. So the program checks if an element it is an element or an internal list?
I think you're over-thinking it. Look at the code:
printList([P|R]):- printList(P),
Right there you can see that printList/1 is being unified with the head of the list. The fact that all the rules of printList/1 match lists and only lists is a fact that you, the human, can immediately see. But Prolog does not "notice" this fact, so if you are to call, say,
printList([1])
the first matching rule is the one above, so it will immediately try to unify printList(1). This will fail, naturally, because 1 is not a list and so doesn't match any of the rules for printList/1. Prolog then backtracks and tries the next rule, which is the one that starts like this:
printList([X|R]):- write(X),
This is clearly going to unify [1] with X = 1, R = [], so it's clearly going to write the first element, the one, and then proceed as usual. There is no magic here involving "internal lists," which as far as I'm aware is not a concept in Prolog at all (if such a thing is treated in the compiler it is well hidden from the user of Prolog).
Prolog isn't psychic; it has to try the rules to see if they fail, even if that attempt is essentially a failing pattern-match in the head of the Horn clause.
I am unable to distinguish your first from your second question so I hope this answers both. :)

prolog - why this strange trace

here is the prolog code (which i sort of follow).
len([],0).
len([_|T],N) :- len(T,X), N is X+1.
and here is the trace for it (im running linux, swi)
[trace] ?- len([d,f,w,c],X).
Call: (7) len([d, f, w, c], _G314) ?
Call: (8) len([f, w, c], _L182) ?
Call: (9) len([w, c], _L201) ?
Call: (10) len([c], _L220) ?
Call: (11) len([], _L239) ?
Exit: (11) len([], 0) ?
^ Call: (11) _L220 is 0+1 ?
^ Exit: (11) 1 is 0+1 ?
Exit: (10) len([c], 1) ?
^ Call: (10) _L201 is 1+1 ?
^ Exit: (10) 2 is 1+1 ?
Exit: (9) len([w, c], 2) ?
^ Call: (9) _L182 is 2+1 ?
^ Exit: (9) 3 is 2+1 ?
Exit: (8) len([f, w, c], 3) ?
^ Call: (8) _G314 is 3+1 ?
^ Exit: (8) 4 is 3+1 ?
Exit: (7) len([d, f, w, c], 4) ?
X = 4.
i know prolog runs down these 'trees' but im having trouble figuring out why the increment to the variable is only done when it is exiting - any explainations of the mechanics of this?
Many thanks!
The reason for this, is that N is X+1 is the last part to the predicate.
Think of it like this: to calculate N is X+1, we need to know the value of X, which is calculated by calling len(T,X). But the process of calculating X requires yet another call to len, all the way to the situation where you end up with an empty list.
It is at that point that the list length is known, namely 0. Thus that value is "returned". Only then 0 + 1 can calculated and "returned". And then 1 + 1. Etc.
Thinking of it another way, observe that for any two predicates a and b, a, b yields true iff both a and b are true. In Prolog, b will only be evaluated if it is known that a is true (otherwise there is no point in evaluating b, since the result is known to be false).
As a result, all additions are done after the recursive calls to len.

Resources