Search code examples
listprologprolog-toplevel

Is there a way to write a length/1 predicate using write/1 to print result?


I have an assigment for school, started learning Prolog recently.
This is the exercise (pretty straightforward):

Write a program in Prolog to find a length of a given list. For example, length([a, b, c, d, e]). should print 5

I really have no clue how to create a length/1 predicate that does this for me. This is the code I have:

length([],0).
length([_|T],N) :- length(T,X), N is X+1. 

Now, I asked my teacher how to turn this to a length/1 predicate, and he told me to use the write/1 predicate. I looked up the write/1 predicate, but I don't see how this will help me writing a length/1 predicate. Any tips/tricks to do this?
To be clear, this is homework.


Solution

  • The solution is easy: impure(Ls) :- length(Ls, L), write(L)..

    However, this is a very bad idea for several reasons.

    A very important one is that things that appear only on your screen cannot be reasoned about within Prolog!

    Thus, if you just write some results with write/1, you cannot really run automatic test cases to see whether your predicate actually behaves as expected. At least writing tests becomes much harder this way.

    In contrast, with your original, purer version of the code (which did not use side-effects), you can easily test for example:

    ?- length([a,b,c], 3).
    true.
    

    and also run several such test cases automatically, and use Prolog to see whether they succeed. For example, a batch of 10,000 test cases may look like (searching for counterexamples):

    ?- between(1, 10_000, L), length(Ls, L),  length([_|Ls], L1), L1 =\= L+1.
    false.
    

    In contrast, how do you test an impure predicate?

    ?- between(1, 10_000, L), length(Ls, L),  impure([_|Ls])  what now??
    

    As you see, it is really hard to reason about the output of a predicate!

    Also, this makes your predicate much less general than your current version! You can no longer use the impure version in other directions. For example, how do you now generate a list of given length? There is no way to supply the length!

    Stay pure folks, and use the Prolog toplevel to obtain answers instead of writing them yourselves on the screen!