为什么在SWI-Prolog版本6.4.1中,0-arity谓词的current_functor/2是假的



我在OS X 7上使用SWI-Prolog版本6.4.1,并且在谓词current_functor/2遇到以下意外行为:

鉴于事实

p(a).
q.

我得到以下查询答案:

?- current_functor(p, Y).
Y = 1 
?- current_functor(q, Y).
false.
?- current_functor(q, 0).
true.

不仅第二个和第三个查询看起来明显不一致,而且第二个查询的失败似乎与SWI-Prolog参考手册不一致,该手册对current_functor/2描述如下:

current_functor(?名字?阿里蒂) 依次将 Name 与名称统一,将 Arity 与系统已知的函子的 arity 统一起来。

谁能帮助我理解为什么谓词以这种方式工作?

编辑:

在解决我测试谓词是否已定义的特定问题(包括某些 0-arity 谓词)方面,我最终遵循了 false 的建议并编写了以下内容:

current_pred(P) :-
    current_predicate(P/_).

TL;DR:不要!

current_functor/2 是一个特定于 SWI 的内置谓词,您在其他任何地方都找不到(除了唯一与历史相关的 DECsystem 10)。此谓词的原因与 SWI 中函子的特定表示有关。简而言之,SWI 在使用之前需要注册每个函子。(在此之前,它需要注册相关的原子。如果不再使用函子会发生什么情况?那么它是否仍然存在?此资源是否被垃圾回收?

回答你的问题:current_functor/2只会对函子成功。没有 arity 0 的函子。arity 为 0 的项称为原子,处理方式不同。

在任何情况下,您都将编写依赖于由一个人维护的单个实现的代码。对于一个更大的项目来说,这不是一个非常安全的赌注。

其他Prolog系统的工作方式不同。它们也需要注册原子,但是他们可以构造任何最多max_arity函子,而无需使用一些进一步的全局资源。出于这个原因,许多系统提供 current_atom/1 .

但即使是这个谓词也是定义不清的。毕竟,原子仍然存在意味着什么?优化编译器可以删除原子从而改变其含义吗?它是否是一种检查应用程序通过一些看起来无害的查询代码使用的机密原子的方法?

这一切真的是一罐蠕虫。不惜一切代价避免它们。也许改用current_predicate


综上所述,如果您仍然认为您需要它,请执行:

current_f(F, A) :-
   current_functor(F, A).
current_f(F, 0) :-
   current_atom(F).

我认为 pl-funct.c 的第 391 行可能存在错误。那行读

if ( fd && fd->arity > 0 && (!nm || nm == fd->name) )

现在我将尝试更正fd->arity >= 0并进行测试...

编辑显然它奏效了:

1 ?- [user].
yy.
|: 
% user://1 compiled 0.00 sec, 2 clauses
true.
2 ?- current_functor(yy,X).
X = 0 ;
false.

我会尝试提交,但我认为我无法 git 访问完整的源代码......

编辑确实,git 拒绝接受我的更改...我将在SWI-Prolog邮件列表中报告。

相关内容

最新更新