用 forall/2 扩展 Prolog 子句

Expanding Prolog clauses with forall/2

我正在使用 clause/2 来转换编译器中的一些 Prolog 子句。我需要用正文替换每个子句的头部,但 clause/2 有时不会按照最初编写的方式扩展子句。

这里,clause/2demo(A,B)扩展为\+ (call(A),\+call(B)),而不是扩展其原始定义:

:- use_module(prolog_to_minizinc).
:- initialization(main).

main :- 
        writeln(forall(A,B)),
        clause(demo(A,B),Clause),
        writeln(Clause).

demo(A,B) :-
    forall(A,B).

是否有另一种方法来扩展子句,而不修改包含 forall/2 的子句?

forall/2 目标的意外扩展是由于 SWI-Prolog 在启动时加载 library(apply_macros)。这个库提供了 forall/2 和其他谓词的扩展代码。查找 library(apply_macros) 的加载方式并非易事,因为在 ~/.config/swi-prolog/init.pl 文件中将 verbose_autoload 标志设置为 true 不会打印所有在启动时自动加载的库。在我的笔记本电脑上,使用当前开发的 git 版本的 SWI-Prolog (8.1.21-82-ge6e1d5376-DIRTY):

?- current_module(apply_macros).
true.

?- module_property(apply_macros, P).
P = class(library) ;
P = file('/Users/pmoura/lib/swipl/library/apply_macros.pl') ;
P = line_count(36) ;
P = exports([expand_phrase/2, expand_phrase/4]) .

?- source_file_property('/Users/pmoura/lib/swipl/library/apply_macros.pl', P).
P = modified(1547476368.0) ;
P = source(file) ;
P = module(apply_macros) ;
P = load_context(nb_set, '/Users/pmoura/lib/swipl/library/nb_set.pl':45, [imports([])]) ;
P = load_count(1) ;
P = number_of_clauses(52).

?- source_file_property('/Users/pmoura/lib/swipl/library/nb_set.pl', P).
P = modified(1547476368.0) ;
P = source(file) ;
P = module(nb_set) ;
P = load_context(solution_sequences, '/Users/pmoura/lib/swipl/library/solution_sequences.pl':46, []) ;
P = load_count(1) ;
P = number_of_clauses(13).

?- source_file_property('/Users/pmoura/lib/swipl/library/solution_sequences.pl', P).
P = modified(1574086719.0) ;
P = source(file) ;
P = module(solution_sequences) ;
P = load_context(editline, '/Users/pmoura/lib/swipl/library/editline.pl':59, []) ;
P = load_count(1) ;
P = number_of_clauses(49).

文件editline.pl提供默认方便的命令行历史记录和其他服务。但是,如果您通过将指令添加到 ~/.config/swi-prolog/init.pl 文件来切换到 readline

:- set_prolog_flag(readline, readline).

然后你得到:

?- [user].
|: a(A,B) :- forall(A,B).
|: % user://1 compiled 0.00 sec, 1 clauses
true.

?- listing(a/2).
% autoloading user:listing/1 from /Users/pmoura/lib/swipl/library/listing
a(A, B) :-
    forall(A, B).

true.

这是一个糟糕的解决方法,但它可能对您有所帮助。