Forall 而不是故障驱动的循环

一些经典Prolog 教科书仍然使用容易混淆且容易出错的故障驱动循环语法,其中 fail 构造用于强制回溯以将目标应用于生成器的每个值。例如,要打印达到给定限制的所有数字:

fdl(X) :- between(1,X,Y), print(Y), fail.
fdl(_).

绝大多数 Modern Prolog 不再需要这种语法,而是提供更高阶的谓词来解决这个问题。

nicer(X) :- forall(between(1,X,Y), print(Y)).

这不仅更容易阅读,而且如果使用可能失败的目标代替打印,它的失败将被正确检测并传递 - 而失败驱动循环中的目标失败与强制失败混淆驱动循环。

Visual Prolog 有这些循环的自定义语法糖,结合函数谓词(见下文):

vploop(X) :- foreach Y = std::fromTo(1,X) do
                 console::write(X)
             end foreach.

虽然这看起来像一个势在必行循环,它仍沿用 Prolog 的规则:尤其是每次迭代的 foreach 是它自己的范围。