如何确保所有模块(以及理想情况下已加载或包含的所有其他文件)都是最新的?发布时use_module(mymodule)
,SICStus 会比较文件的修改日期mymodule.pl
并重新加载(如果更新)。此外include
-ed 文件将触发重新编译。但它不会重新检查mymodule
.
简而言之,我怎样才能获得与 SWI 提供的类似功能make/0
?
如何确保所有模块(以及理想情况下已加载或包含的所有其他文件)都是最新的?发布时use_module(mymodule)
,SICStus 会比较文件的修改日期mymodule.pl
并重新加载(如果更新)。此外include
-ed 文件将触发重新编译。但它不会重新检查mymodule
.
简而言之,我怎样才能获得与 SWI 提供的类似功能make/0
?
SICStus Prolog 中没有任何东西可以提供这种功能。
一个大问题是当前的 Prolog 过于动态,以至于 make/0 之类的东西无法可靠地工作,除非是非常简单的情况。使用术语扩展、加载期间执行的目标(包括常见的文件加载目标)等功能,不可能知道如何可靠地重新加载文件。我没有仔细看过它,但大概是 SWI Prolog 中的 make/0 也有同样的问题。
我通常只是重新启动 Prolog 进程并再次加载“主”文件,即加载我需要的所有内容的文件。
PS。我无法在评论中获得代码格式,所以我把它放在这里:示例为什么 make/0 需要防范 'user' 作为来自 current_module/2 的文件:
| ?- [user].
% compiling user...
| :- module(m,[p/0]). p. end_of_file.
% module m imported into user
% compiled user in module m, 0 msec 752 bytes
yes
| ?- current_module(M, F), F==user.
F = user,
M = m ? ;
no
| ?-
到目前为止,我已经经历了几个黑客:
SICStus 始终源自ensure_loaded/1
Quintus,它不仅是指令(如 ISO 中的指令),而且还是命令。所以我编写了自己的 make-predicate 来简单地枚举所有文件:
l :-
ensure_loaded([f1,f2,f3]).
发布后l.
,仅重新加载同时修改的那些文件。
可能,我也可以这样写——我会读到意思(原文如此):
l :-
\+ ( source_file(F), \+ ensure_loaded(F) ).
有了模块,事情发生了一些变化。一方面,有些文件是手动加载到模块中的,例如ensure_loaded(module:[f1,f2,f3])
,然后是干净的模块。事实证明,有一种方法可以全局确保模块已加载——无需干扰实际的导入列表,只需说明use_module(m1, [])
哪个又是指令和命令。关键是导致模块被重新检查和重新加载的空列表,但是由于空列表可以在任何地方进行声明。
同时,我使用以下模块:
:- module(make,[make/0]).
make :-
\+ ( current_module(_, F), \+ use_module(F, []) ).
这适用于所有“合法”模块——只要接口不变。我仍然不喜欢它的冗长:对于每个已检查和未修改的模块,都有一个消息行。因此,当我只想检查所有内容是否都是最新的时,我会得到一个充满此类消息的页面。理想情况下,此类消息仅在发生新情况时才会显示。
| ?- make.
% module m2 imported into make
% module m1 imported into make
% module SU_messages imported into make
yes
| ?- make.
% module m2 imported into make
% module m1 imported into make
% module SU_messages imported into make
yes
改进的版本 考虑了@PerMildner 的评论。
如果它们与一个模块相关,则可以重新加载更多文件。特别是,加载到模块user
中的文件像.sicstusrc
. 有关完整代码,请参见上面的链接。
% reload files that are implicitly modules, but that are still simple to reload
\+ (
source_file(F),
F \== user,
\+ current_module(_, F), % not officially declared as a module
setof(M,
P^ExF^ExM^(
source_file(M:P,F),
\+ current_module(M,ExF), % not part of an official module
\+ predicate_property(M:P,multifile),
\+ predicate_property(M:P,imported_from(ExM))
),[M]), % only one module per file, others are too complex
\+ ensure_loaded(M:F)
).
请注意,在 SWI 中既不比较文件修改日期,ensure_loaded/1
也不use_module/2
比较文件修改日期。因此两者都不能用于确保加载文件的最新版本。