我正在使用ECLiPSe 6.1。我有一个维度为N x N
的变量数组,我们称其为Vars
。现在,我用my_procedure(Vars[1..N,1..2])
调用一个过程。
在过程(my_procedure(List) :- ...
)中,使用了(foreach(X, List) do ...)
之类的东西。
这行不通。在循环L is List
(而不是L
)之前,我必须在过程内部编写类似List
的内容。
这是为什么?我该如何解决呢?因为稍后我尝试使用flatten(Vars[1..N,1..2])
调用该过程,然后情况变得更糟。
我开始使用collection_to_list/2
(与flatten
一起解决此问题,但我想知道是否有一种优雅的解决方法。
答案 0 :(得分:2)
让我详细说明一下,因为您的问题突出了Prolog / ECLiPSe的功能,该功能经常使来自其他编程语言的用户感到惊讶:
也许最公然的例子是看起来像“算术表达式”的东西:
?- writeln(3+4).
3 + 4
Prolog仅将参数3+4
作为符号项+(3,4)
,并将其传递给未解释的writeln / 1。将术语作为参数传递给用户定义的谓词不会改变这一点,在调用时没有隐式求值:
p(X) :- writeln(received(X)).
?- p(3+4).
received(3 + 4)
如果要将参数解释为算术表达式并对其求值,则必须明确请求:
parith(Expr) :- Num is Expr, writeln(evaluated_to(Num)).
?- parith(3 + 4).
evaluated_to(7)
ECLiPSe中的数组访问表达式的行为相同。它们只是符号表达式,直到被理解它们的谓词明确评估:
?- Array = [](11,22,33), p(Array[2]).
received([](11,22,33)[2])
?- Array = [](11,22,33), parith(Array[2]).
evaluated_to(22)
因此,最后回到最初的问题:当您调用my_procedure(Vars[1..N,1..2])
时,传递的参数是符号表达式Vars[1..N,1..2]
,这就是my_procedure/1
收到的内容。要将其转换为所需的平面列表,必须将其解释为产生列表的表达式,并且
collection_to_list/2(或者从ECLiPSe 7.0开始,eval_to_list/2)完全可以做到:
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])