这是一个有趣的问题。首先我认为有两个
各种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,例如solve/1,具有谓词属性。因为
functor/3 通常没有元谓词声明。还
通过functor/3传输模块信息到
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,:).
原版解释器,也可以处理模块,然后
内容如下。不幸的是,需要进一步的谓词,
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).
上面实现了冒号 (:)/2 的局部语义,
与结肠的相当深远的语义相比
(:)/2 如 ISO 模块标准中所述。远方
达到语义在所有文字上赋予模块名称
的一个查询。本地语义只需要一个合格的
文字,只是将模块名称应用于该文字。
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。
再见