遍历作为子数组的列表

Looping through a list which is a subarray

我正在使用 ECLiPSe 6.1。我有一个维度为 N x N 的变量数组,我们称它为 Vars。现在我用 my_procedure(Vars[1..N,1..2]).

调用一个过程

在过程 (my_procedure(List) :- ...) 中,使用了类似 (foreach(X, List) do ...) 的东西。 这是行不通的。在循环 L(而不是 List)之前,我必须在程序中写类似 L is List 的内容才能使其工作。

这是为什么?我该如何解决?因为稍后我尝试用 flatten(Vars[1..N,1..2]) 调用该过程然后它变得更糟。

我开始使用 collection_to_list/2(和 flatten)来解决这个问题,但我想知道是否有一种优雅的方法来解决它。

让我详细说明一下,因为您的问题突出了 Prolog/ECLiPSe 的一个功能,该功能经常让来自其他编程语言的用户感到惊讶:

  • 默认情况下,每个 term/expression 只是一个 符号 结构,没有内在意义
  • 此类符号结构的任何 interpretation/evaluation 仅在特定上下文中出现,或在明确请求时出现

也许最明显的例子是看起来像 "arithmetic expression":

?- 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 (or, starting from 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])