遍历作为子数组的列表
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])
我正在使用 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])