total_item([],0).
total_item([_|Rest],N) :- total_item(Rest,C), N is C+1.
This program takes an array as input and count the total number of item in that list. But I am not getting what exactly variable N and C stores. Any explanation would be appreciate. Thank you
Read it backwards:
total_item
maps0
to[]
(relates the two).with
C
mapped toRest
,C+1
is mapped to[_ | Rest]
-- the list one element longer than the listRest
.See this with the most general query working in the generative fashion:
Will Ness answer should have provided you with a clear understanding of that predicate definition. But there's more that you can learn from it. Let's do a trace of a simple call. Here I'm using GNU Prolog but most Prolog system provide the same trace functionality:
You can see in the first four lines that the predicate results in walking the list until the end and only then we compute the pending
N is C + 1
goals. Each element in the list results in one pending arithmetic evaluation goal. These pending goals must be stored in a stack until the recursive call to thetotal_item /2
predicate terminates. As a consequence, computing the length of a list of size N requires space (for the stack) proportional to N. I.e. this predicate definition is not tail-recursive.But we can rewrite the predicate, making it tail-recursive to improve its space complexity by using an accumulator. An accumulator is an argument that stores intermediate results, in this case, the count so far of the number of elements in the list:
Let's trace the same goal:
Notice that how the accumulator, the second argument in the auxiliary
total_item/3
predicate is incremented as we walk thew list. With this definition, there are no pending goals, which means the space complexity is O(1) instead of O(N). Much better.