1

我正在使用 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(with flatten) 来解决这个问题,但我想知道是否有一种优雅的方式来解决它。

4

1 回答 1

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])
于 2019-04-28T17:18:25.723 回答