0
votes

I'm trying to build a chess game in Prolog, and I started by studying this Stack Overflow post How to access two dimensional array in prolog and how to loop each element in it, because I think the chess game involves data of the board and pieces in a form of two dimensional array. So right now I'm trying to experiment with a simpler array to understand how it works first.

By making the most of the example code provided in the link above, I wrote a print_array(Array) predicate, along with the code below.

arraysample([[[1],[2],[3]],[[4],[5],[6]],[[7],[8],[9]]]).

array1([[1],[2],[3],[4],[5]]).

print_array(Array):-
    print_rows(Array).

print_rows([]):-
    write(''),nl.    % trying to create a new line before moving on to the next row, 
                     % but at this moment it's not working
print_rows([Row|Rows]):-
    print_row(Row),
    print_rows(Rows).

print_row([]).
print_row([Cell|Columns]):-
    print_cell(Cell),
    print_row(Columns).

print_cell(Cell):-
    write(Cell),
    write(' ').

and when I call the predicate with a hard-coded array like this, it properly prints out the array with the result true.

?- print_array([[[1],[2],[3]],[[4],[5],[6]],[[7],[8],[9]]]).
[1] [2] [3] [4] [5] [6] [7] [8] [9] 
true.

But when I use the array name, it fails.

?- print_array(array1).
false.

And when I used trace to see what was going on, it only displayed me something like this.

?- trace(print_array(array1)).
%         print_array/1: [call,redo,exit,fail]
true.

Why does calling the predicate with an array name fail while it works with a hard-coded array? How can I get it to work with an array name as well?

NOTE: Please provide me with some concrete examples by showing me some code when you answer my question, just like I pasted my code in my question. If you are thinking of posting an abstract comment like "Read the Prolog documentation, period.", which is not an answer for any specific question at all, don't write anything in the first place. Thanks in advance.

1
If you first enter trace., then enter your query print_array(array1). separately, you'll get detailed query steps.lurker
You're misunderstanding a fundamental aspect of Prolog. array1([[1],[2],[3],[4],[5]]). asserts a fact array1 with argument, [[1],[2],[3],[4],[5]]. array1 is not a variable representing the value [[1],[2],[3],[4],[5]]. So calling print_array(array1) does not subsitute [[1],[2],[3],[4],[5]] for array1 in the call. print_array just sees an atom, array1 which is not a list so it fails immediately. Try, array1(X), print_array(X)..lurker

1 Answers

2
votes

You're misunderstanding a fundamental aspect of Prolog. array1([[1],[2],[3],[4],[5]]). asserts a fact array1 with argument, [[1],[2],[3],[4],[5]]. array1 is not a variable representing the value [[1],[2],[3],[4],[5]]. So calling print_array(array1) does not subsitute [[1],[2],[3],[4],[5]] for array1 in the call. print_array just sees an atom, array1 which is not a list so it fails immediately.

On the query print_array(array1), Prolog attempts to unify this term with any print_array/1 facts or heads of predicates you have. It finds print_array(Array) and is able to unify it with Array = array1.

It then calls print_rows(array1). It follows the same process. However, in this case, each predicate head for print_rows/1 involves a list:

print_rows([]):- ...
print_rows([Row|Rows]):- ...

Prolog attempts to unify the atom array1 with [] and fails (try array1 = []. at the Prolog prompt and it will fail). It then attempts to unify array1 with [Row|Rows] and fails (try array1 = [Row|Rows]. at the Prolog prompt, and it will fail).

This the entire call print_array(array1) fails as there are no more alternatives.

Instead of print_array(array1)., do this at the Prolog prompt:

:- array1(Array), print_array(Array).

array1(Array) will query the array1/1 facts and result in a solution, instantiating Array with [[1],[2],[3],[4],[5]]. Then print_array(Array) will be print_array([[1],[2],[3],[4],[5]]).