这是一个有趣的问题。首先,我认为有两种predicate_property/2
谓词。第一种采用可调用对象,旨在与例如香草解释器和内置插件(如 , 等)顺利工作
write/1
,nl/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/2
,sys_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
。
再见