Prolog:你如何在两个列表之间进行迭代(nest for-loop)?

Nat*_*tti 3 list prolog

我本周刚开始学习Prolog,所以我不确定Prolog中是否可以使用for循环.我在Prolog中有两个列表

stringList([hi,hello],[bye,later],X).
Run Code Online (Sandbox Code Playgroud)

如何创建每个列表包含一个元素的新解决方案列表?

所以输出应该是:

X = [hi,bye]
X = [hi,later]
X = [hello,bye]
X = [hello,later]
Run Code Online (Sandbox Code Playgroud)

mat*_*mat 5

使用Prolog时的一个主要优点是您可以此类循环委派给Prolog 引擎.您不必明确地编写它们.

例如,在您的情况下,以这种方式思考问题:什么持有(或应该持有)  X

我们可以说:

  1. X是一个包含两个元素的列表[A,B].
  2. A 是由第一个参数表示的列表的成员.
  3. B 是由第二个参数表示的列表的成员.

所以,在Prolog中:

one_from_each(As, Bs, [A,B]) :-
    member(A, As),
    member(B, Bs).

示例查询:

?- one_from_each([hi,hello],[bye,later], X).
X = [hi, bye] ;
X = [hi, later] ;
X = [hello, bye] ;
X = [hello, later].

它也适用于其他方向:

?- one_from_each(As, Bs, [hi,bye]).
As = [hi|_4656],
Bs = [bye|_4662] ;
As = [hi|_4656],
Bs = [_4660, bye|_4668] ;
As = [hi|_4656],
Bs = [_4660, _4666, bye|_4674] .

因此,整个问题有点误导.在Prolog中编码时,请始终询问:我如何制定应该保留的内容?一旦你有这样的表述,你可以留下搜索Prolog引擎的解决方案!

如果你愿意,你可以更明确.例如:

one_from_each([], _) --> [].
one_from_each([L|Ls], Rs) -->
    one_from_each_(Rs, L),
    one_from_each(Ls, Rs).

one_from_each_([], _) --> [].
one_from_each_([R|Rs], L) -->
    [[L,R]],
    one_from_each_(Rs, L).

例:

?- phrase(one_from_each([hi,hello],[bye,later]), Ls).
Ls = [[hi, bye], [hi, later], [hello, bye], [hello, later]].

这有时被称为空间表示,因为现在不再在回溯(时间表示)上找到解,而是明确表示.

从中可以看出,"循环"对应于递归定义.