I'm using ECLiPSe 6.1. I have an array of variables of dimension N x N
, let's call it Vars
. Now I call a procedure with, say, my_procedure(Vars[1..N,1..2])
.
Inside the procedure (my_procedure(List) :- ...
), something like (foreach(X, List) do ...)
is used.
This doesn't work. I have to write something like L is List
inside the procedure before looping over L
(instead of List
) to make it work.
Why is this? And how can I address it? Because later on I try to call the procedure with flatten(Vars[1..N,1..2])
and then it gets even worse.
I started using collection_to_list/2
(with flatten
) to resolve the issue, but I was wondering if there's an elegant way to address it.
Let me elaborate a bit, because your question highlights a feature of Prolog/ECLiPSe that regularly surprises users coming from other programming languages:
Maybe the most blatant example is with what looks like an "arithmetic expression":
?- writeln(3+4).
3 + 4
Prolog takes the argument 3+4
simply as the symbolic term +(3,4)
and passes it to writeln/1, uninterpreted. Passing a term as an argument to a user-defined predicate doesn't change this, there is no implicit evaluation at call time:
p(X) :- writeln(received(X)).
?- p(3+4).
received(3 + 4)
If we want to interpret the argument as an arithmetic expression and evaluate it, we have to request this explicitly:
parith(Expr) :- Num is Expr, writeln(evaluated_to(Num)).
?- parith(3 + 4).
evaluated_to(7)
Array access expressions in ECLiPSe behave in the same way. They are just symbolic expressions until explicitly evaluated by a predicate that understands them:
?- Array = [](11,22,33), p(Array[2]).
received([](11,22,33)[2])
?- Array = [](11,22,33), parith(Array[2]).
evaluated_to(22)
So, to finally come back to your original problem: when you call my_procedure(Vars[1..N,1..2])
, the argument that gets passed is the symbolic expression Vars[1..N,1..2]
, and this is what my_procedure/1
receives. To turn that into the flat list that you want, it has to be interpreted as an expression that yields a list, and
collection_to_list/2 (or, starting from ECLiPSe 7.0, eval_to_list/2) do exactly that:
plist(Expr) :- eval_to_list(Expr, List), writeln(evaluated_to(List)).
?- A = [](11, 22, 33), p(A[2 .. 3]).
received([](11, 22, 33)[2 .. 3])
?- A = [](11, 22, 33), plist(A[2 .. 3]).
evaluated_to([22, 33])