Prolog 如何用模块重写用户谓词

Prolog 如何用模块重写用户谓词,prolog,swi-prolog,Prolog,Swi Prolog,假设我有一个名为foo(在foo.pl中定义)的模块。此模块进行术语扩展,例如: :- module(foo,[term_expansion/2]). term_expansion(A,A) :- print A. 当然,真正的代码对术语做了更复杂的处理 现在我想将这个库导入一个文件,比如test.pl: :- use_module(foo). fact(a). 但是,当使用swi prolog时,我得到以下错误: ERROR: Cannot import foo:term_exp

假设我有一个名为
foo
(在
foo.pl
中定义)的模块。此模块进行术语扩展,例如:

:- module(foo,[term_expansion/2]).

term_expansion(A,A) :-
    print A.
当然,真正的代码对术语做了更复杂的处理

现在我想将这个库导入一个文件,比如
test.pl

:- use_module(foo).
fact(a).
但是,当使用
swi prolog
时,我得到以下错误:

ERROR: Cannot import foo:term_expansion/2 into module user: name clash

如何解决此错误?

术语扩展谓词通常(它们不是标准的)声明为多文件(可能是动态)谓词。在SWI-Prolog的特定情况下,术语扩展机制已经定义并调用伪模块
user
术语扩展/2
谓词的定义。因此,一个可能的解决方案是写:

:- module(foo).

:- multifile(user:term_expansion/2).
:- dynamic(user:term_expansion/2).

user:term_expansion(A,A) :-
    print(A).
在加载要进行术语扩展的文件之前,应该只需要加载此模块的定义


关于后续问题,即为什么默认情况下未声明
术语\u expansion/2
谓词为多文件。我可以对你的问题给出两种不同的解释。这两个问题我都会解决。(1) 为什么需要重复
multifile/1
指令?ISO Prolog标准意味着多文件谓词应该在包含其子句的所有文件中声明为多文件(我说是暗示而不是指定,因为标准谈论的是“Prolog文本”,而不是文件)。实际上,SWI Prolog在这里是相当自由的,但是重复这些指令是一种很好的做法,而且当其他系统在这方面更严格地遵循标准时。(2) 为什么术语扩展谓词首先必须声明为多文件(和动态的)?这取决于实施情况。例如,在术语扩展机制的Logtalk实现中,它们既不是多文件也不是动态的。

您是说要覆盖SWI Prolog的预定义谓词
术语扩展
?是的。库应该将
test.pl
的理论修改为另一种理论……它们在默认情况下不被声明为多文件有什么原因吗?请参阅上面我的扩展回复。给其他读者的提示是:将谓词
user:term_expansion/2
声明为动态是不必要的——在某些情况下(我认为是这样)将其声明为多文件就足够了。