3

换句话说,应该是0还是:其他?Prolog 系统 SICStus、YAP 和 SWI 都将其表示为:. 这合适吗?不应该是 a 0which 表示可以被调用的术语call/1吗?

要检查您的系统类型:

| ?- predicate_property(predicate_property(_,_),P).
P = (meta_predicate predicate_property(:,?)) ? ;
P = built_in ? ;
P = jitted ? ;
no

我应该补充一点,元参数——至少在这里使用的形式——不能保证我们期望从纯关系中得到相同的代数属性:

?- S=user:false, predicate_property(S,built_in).
S = user:false.

?- predicate_property(S,built_in), S=user:false.
false.

这是来自 ISO/IEC 13211-2 的相关部分:

7.2.2 谓词属性/2

7.2.2.1 说明

predicate_property(Prototype, Property)如果与参数关联的过程具有谓词属性 ,则
在模块的调用上下文中为真。M
PrototypeProperty

...

7.2.2.2 模板和模式

predicate_property(+prototype, ?predicate_property)

7.2.2.3 错误

a)Prototype是一个变量
—— instantiation_error

...

c)Prototype既不是变量也不是可调用项
type_error(callable, Prototype).

...

7.2.2.4 示例

Goals attempted in the context of the module
bar.

predicate_property(q(X), exported).
    succeeds, X is not instantiated.

...

4

1 回答 1

2

这是一个有趣的问题。首先,我认为有两种predicate_property/2谓词。第一种采用可调用对象,旨在与例如香草解释器和内置插件(如 , 等)顺利工作 write/1nl/0即:

solve((A,B)) :- !, solve(A), solve(B).
solve(A) :- predicate_property(A, built_in), !, A.
solve(A) :- clause(A,B), solve(B).

对于第一种,我猜 0 元参数说明符可以正常工作。第二种predicate_property/2 谓词与谓词指示符一起使用。可调用和谓词指示符都是 ISO 核心标准中已经定义的概念。

谓词指示符的形式为 F/N,其中 F 是原子,N 是整数。如果存在模块,事情会变得有点复杂,特别是因为 (:)/2 与 (/)/2 的运算符优先级。如果谓词属性与谓词指示符一起使用,我们仍然可以编写 vanilla 解释器:

solve((A,B)) :- !, solve(A), solve(B).
solve(A) :- functor(A,F,N), predicate_property(F/N, built_in), !, A.
solve(A) :- clause(A,B), solve(B).

在这里,我们松开了可能的元参数 0,例如 of solve/1,与谓词属性的连接。因为 functor/3通常没有元谓词声明。functor/3同样通过to 传输模块信息predicate_property/2也是不可能的,因为functor/3它与模块无关,它通常没有可以处理包含模块限定的参数的实现。

现在有两个问题:
1)我们可以给类型和/或我们应该给诸如functor/3.
2)我们可以扩展functor/3以便它可以传达模块资格。

以下是我的想法:
1)需要更精细的类型系统。一种允许使用多种类型重载谓词的方法。例如functor/3可以有两种类型:

  :- meta_predicate functor(?,?,?).
  :- meta_predicate functor(0,?,?).

重载多种类型的真正威力只会在诸如 (=)/2 之类的谓词中发挥作用。在这里,我们将拥有:

  :- meta_predicate =(?,?).
  :- meta_predicate =(0,0).

因此允许更多的类型推断,如果 (=)/2 的一侧是一个目标,我们可以推断出另一侧也是一个目标。

但是事情并不是那么简单,可能还有一种类型转换的形式,或者其他一些限制重载的机制是有意义的。仅引入元谓词指令未涵盖的内容。这将需要在条款和目标中进一步构建。

学习 lambda Prolog 或一些依赖类型系统可能是有利的。例如 (=)/2 可以被视为由类型 A 参数化,即:

 :- meta_predicate =(A,A).

2) 对于 Jekejeke Prolog,我提供了另一种 functor/3 实现。谓词是sys_modfunc_site/2。它像 一样双向工作functor/3,但返回并接受谓词指示符作为一个整体。以下是一些示例运行:

 ?- sys_modfunc_site(a:b(x,y), X).
 X = a:b/2
 ?- sys_modfunc_site(X, a:b/2).
 X = a:b(_A,_B)

谓词的结果可以称为广义谓词指示符。这是 SWI-Prolog 已经理解的内容,例如listing/1. 所以它可以有相同的元参数规范listing/1。这是当前的:在 SWI-Prolog 中。所以我们会有,随后predicate_property/2会在它的第一个参数中使用 ::

 :- meta_predicate sys_modfunc_site(?,?).
 :- meta_predicate sys_modfunc_site(0,:).

vanilla 解释器,也可以处理模块,然后读取如下。不幸的是,需要进一步的谓词 sys_indicator_colon/2,它将合格的谓词指示符压缩为普通的谓词指示符,因为 predicate_property/2出于效率原因我们不理解广义谓词指示符:

solve((A,B)) :- !, solve(A), solve(B).
solve(A) :- 
      sys_modfunc_site(A,I), 
      sys_indicator_colon(J,I), 
      predicate_property(J, built_in), !, A.
solve(A) :- clause(A,B), solve(B).

与 ISO 模块标准中描述的冒号 (:)/2 的相当深远的语义相比,上述实现了冒号 (:)/2 的局部语义。影响深远的语义将模块名称归因于查询的所有文字。本地语义只需要一个合格的文字,并将模块名称应用于该文字。

Jekejeke 仅实现本地语义,并进一步规定调用站点不会更改。因此,在幕后 sys_modfunc_site/2sys_indicator_colon/2还必须转移调用站点,以便predicate_property/2对不合格的谓词做出正确的决定,即通过尊重导入等来解析谓词名称。

最后一点结语:
Jekejeke Prolog 的调用站点传输是纯运行时的事情,不需要一些编译时操作,尤其是在编译时不需要特别添加模块限定符。因此,某些代数性质得以保留。例如假设我们有以下子句:

 ?- [user].
 foo:bar.
 ^D

然后以下事情正常工作,因为不仅sys_modfunc_site/2 是双向的,而且sys_indicator_colon/2

  ?- S = foo:bar/0, sys_indicator_colon(R,S), predicate_property(R,static).
  S = foo:bar/0,
  R = 'foo%bar'/0
  ?- predicate_property(R,static), sys_indicator_colon(R,S), S = foo:bar/0.
  R = 'foo%bar'/0,
  S = foo:bar/0

当然predicate_property/2适用于不同的输入和输出模式。但我猜 SWI-Prolog 现象首先存在一个问题,即裸骨变量以当前模块为前缀。而且既然false不在user,而是在system,就不会显示了false。在输出模式下,它不会显示分辨率相等的谓词。在 SWI-Prolog 中查看:

 ?- predicate_property(X, built_in), write(X), nl, fail; true.
 portray(_G2778)
 ignore(_G2778)
 ...
 ?- predicate_property(user:X, built_in), write(X), nl, fail; true.
 prolog_load_file(_G71,_G72)
 portray(_G71)
 ...
 ?- predicate_property(system:X, built_in), write(X), nl, fail; true.
 ...
 false
 ...

但是,即使 SWI-Prolog predicate_property/2 谓词允许条形变量,即输出目标,我们也会看到在远距离语义中的交换性比在局部语义中要少。在深远的语义M:G意味着解释G 模块内部M,即尊重模块的导入M,这可能会相当大地转置函子。

user:false意义 深远的语义是原因system:false。另一方面,在局部语义中,M:G 意味着M:G没有别的,我们更经常拥有代数性质。在本地语义user:false中永远不会意味着system:false

再见

于 2014-06-30T19:22:20.117 回答