There are some problems here with the predicate:
- you use
S and T as row number and column number, but S is the head of the list, and T the tail here. Since the list of indices is a list of lists, that means S will be a list, and T a list of lists;
- you do not use recursion to generate a list of values, so if we fix the above, then it will still - at most - yield a specific value; and
- the base predicate is too restrictive, since it assumes that the matrix (the second parameter), should be empty. This does not makes sense, since normally the matrix will be passed without any changes. Regardless of the matrix, if the list of indices is empty, then so is the list of values.
explicit recursion
So if we rewrite the predicate, there are two rules:
the base case: in case the list of indices is empty, then regardless of the matrix, the list of values is empty as well:
cell_values([], _, []).
in the recursive cass, we match the first list with [[R, C] | T], so R is the row number, and C the column number, T is the list of remaining lists to process, so we perform the nth0/3 as demonstrated in the question, but with R and C, and the cell value V is prepended to the result list [V|VT], the VT is then used in the recursive call to obtain more elements:
cell_values([[R, C]| T], M, [V|VT]) :-
nth0(R, M, Row),
nth0(C, Row, V),
cell_values(T, M, VT).
Or putting these together:
cell_values([], _, []).
cell_values([[R, C]| T], M, [V|VT]) :-
nth0(R, M, Row),
nth0(C, Row, V),
cell_values(T, M, VT).
maplist/3
Processing lists is a rather common thing to do, so we might be interested in using maplist/3, and write a predicate that only processes a single sublist, like:
cell_value(M, [R, C], V) :-
nth0(R, M, Row),
nth0(C, Row, V).
Then we can define the predicate cell_values like:
cell_values(Ixs, M, Vs) :-
maplist(cell_value(M), Ixs, Vs).