Suppose we have the following:
edge(a, 1, 10).
edge(b, 2, 20).
edge(c, 3, 30).
edge(d, 4, 40).
I want to extract a matrix representation (M
) of these facts, such that
M = [[a,b,c,d],[1,2,3,4],[10,20,30,40]]
Here's a no-brainer solution:
edgeMatrix(M) :-
findall(A, edge(A, _, _), As),
findall(B, edge(_, B, _), Bs),
findall(C, edge(_, _, C), Cs),
M = [As, Bs, Cs].
There are some problems to this approach, however, viz:
- we traverse the database n times, where n is the number of arguments; and
- this doesn't generalize very well to an arbitrary n.
So the question is: what is the most idiomatic way to achieve this in Prolog?
What about:
Now you can simply import the
transpose/2
matrix fromclpfd
module, or implement one yourself like in this answer (yeah I know that's quite lazy, but what is the point of reinventing the wheel?).If I run this in
swipl
, I get:which looks exactly like you want.
You can of course say that there is still some computational overhead to calculate the
transpose/2
, but the collecting phase is done only once (and if these are not simply facts, but answers from clauses as well) which can be expensive as well, and furthermore I think a module will implement clauses probably very efficiently anyway.