SWI-Prolog 分区谓词在 REPL 中的工作方式与在程序中不同

SWI-Prolog partition predicate works differently in REPL than in programme

我使用 SWISH 以这种方式实现了快速排序:

qsort([],[]).
qsort([H|T],S) :-
  partition([X,O]>>compare(O,X,H),T,L,E,G),
  qsort(L,A),
  qsort(G,Z),
  append([A,[H|E],Z],S).

main :-
  length(L,22),
  maplist(random(0,9),L),
  qsort(L,S),
  maplist(writeln,[L,S]).

无法正常工作。输入和输出列表是相同的。然而,当我在右侧的 REPL 中 运行 时: length(S,22), maplist(random(0,9),S),[H|T]=S, partition([X,O]>>compare(O,X,H),T,L,E,G).

随机列表确实得到了排序。哪里不一样?

当我在[X,O]>>compare(O,X,H)前面添加{H}/时它起作用了。可能是顶层不需要(但允许)预期行为的错误。不过我也不是很清楚,欢迎有识之士解答。

编译 qsort/2 谓词的第二个子句时,除了在编译 lambda 表达式时它是一个变量外,没有关于 H 的信息。在本地 lambda 参数中找不到的 lambda 表达式中出现的任何变量都必须使用 {}/1 结构声明。但是,当 运行 您在顶级解释器中查询时,在解释 lambda 表达式时,H 已绑定,因此不再是变量(使用 {}/1 构造不必要)。

请注意,这里有几个细节在发挥作用,它们超出了 lambda 库本身的范围:(1) 编译器是否在编译时识别出您正在调用带有 lambda 参数的元谓词表达? (2) 如何解释顶级查询?完整查询是首先完全编译还是元解释?这些细节取决于系统本身。