遍历作为子数组的列表

时间:2019-04-27 17:24:24

标签: arrays list prolog eclipse-clp

我正在使用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一起解决此问题,但我想知道是否有一种优雅的解决方法。

1 个答案:

答案 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])