Prolog evaluation of unknown variables

69 views Asked by At

Consider this:

list_length([], 0).
list_length([H|T], N) :- list_length(T, N - 1).

It doesn't give a compilation error, but it doesn't work.

my thinking is:

suppose i call list_length([1], N)

we query list_length([], N - 1)

it tells you that N - 1 = 0

it finds out N is 1 and returns that value of N.

Instead, with gprolog, it tells me no.

In particular, it is also surprising it compiles, given something like:

?- 1 - 1.
uncaught exception: error(existence_error(procedure,(-)/2),top_level/0)
1

There are 1 answers

0
rajashekar On

- is not always an arithmetic operator. N - 1 = 0 will not succeed with N = 1 because = is not arithmetic constraint solver.

If you are using gprolog, N - 1 #= 0 will give you N = 1. Your code will work with this:

list_length([], N) :- N #= 0.
list_length([H|T], N) :- list_length(T, N - 1).

list_length([], 0) is equivalent to list_length([], N) :- N = 0, so it all comes down to, = vs #=.

  • = does unification,
  • #= does arithmetic constraint solving.
| ?- list_length([1, 2, 3], N).
      1    1  Call: list_length([1,2,3],_29) ? 
      2    2  Call: list_length([2,3],_29-1) ? 
      3    3  Call: list_length([3],_29-1-1) ? 
      4    4  Call: list_length([],_29-1-1-1) ? 
      5    5  Call: _29-1-1-1#=0 ? 
      5    5  Exit: 3-1-1-1#=0 ?                  <--------here
      4    4  Exit: list_length([],3-1-1-1) ? 
      3    3  Exit: list_length([3],3-1-1) ? 
      2    2  Exit: list_length([2,3],3-1) ? 
      1    1  Exit: list_length([1,2,3],3) ? 

N = 3

yes

You can see in a already linked question, there are multiple better ways to do this.