5

使用SWI-Prolog(多线程,64 位,版本 7.3.5),我们一步一步进行:

  1. 在模块中定义非终结符(发音:“ di-SEE-goh ”):a//1dcgAux

    :- 模块(dcgAux,[a//1])。
    
    一(0)-> []。
    a(s(N)) --> [a], a(N)。
    
  2. 运行以下查询 - 使用phrase/2and apply:foldl/4

    ?- 使用模块([库(应用),dcgAux])。
    真的。
    
    ?- 短语( foldl( a,[s(0),s(s(0))]),[a,a,a])。
    真的。
    
    ?- 短语( foldl(dcgAux:a,[s(0),s(s(0))]),[a,a,a])。
    真的。
    
    ?- 短语(应用:折叠(dcgAux:a,[s(0),s(s(0))]),[a,a,a])。
    真的。
    
    ?- 短语(应用:折叠(a,[s(0),s(s(0))]),[a,a,a])。
    错误:应用:foldl_/4:未定义的过程:应用:a/3
    

    нет!相当惊喜——而且不是一个好惊喜。我们是否错过了一些未知的未知数?

  3. 为了摆脱上述恼人的行为,我们必须首先找出导致它的原因:

    ?- import_module(apply,M), M=user。
    的。
    
    ?- 短语(应用:折叠(a,[s(0),s(s(0))]),[a,a,a])。
    错误:应用:foldl_/4:未定义的过程:应用:a/3
    
    ?- add_import_module(应用,用户,结束)。
    真的。
    
    ?- import_module(apply,M), M=user。%sic!
    M = 用户。% `?- import_module(apply,user).` 失败!
    
    ?- 短语(应用:折叠(a,[s(0),s(s(0))]),[a,a,a])。
    真的

这是怎么回事?我的看法是这样的:

  • 传递给目标的模块扩展foldl/4是有限的。
  • 引用SWI-Prolog 手册页import_module/2

    所有普通模块仅从用户导入,从系统导入。

  • SWI 的library(apply)唯一“继承”自system,但不是user

  • 如果我们将模块克隆applyapplY(并传播新的模块名称),我们观察到:

    ?- 使用模块(应用)。
    真的。
    
    ?- 短语(应用 : foldl (a,[s(0),s(s(0))]),[a,a,a])。% 是:错误为
    。% 现在好了!
    

请分享您对我可以/应该如何进行的想法!

(我还没有对其他 Prolog 处理器进行过类似的实验。)

4

1 回答 1

6

这是 Quintus 传统中基于谓词的模块系统的固有特性/错误。也就是说,这个模块系统首先是为 Quintus Prolog 开发的。它随后被 SICStus(在 0.7 1之后)采用,然后(或多或少)被 13211-2 采用,然后被 YAP 采用,并且(经过一些修改)被 SWI 采用。

这里的问题是明确限定的确切含义。只要目标不是元谓词,事情就很容易解决:采用最内层限定的模块。但是,一旦有了元谓词,就需要通知元参数该模块;或不。如果元参数被告知,我们说冒号设置了调用上下文,如果没有,那么为此目的需要一些其他方法。

在 Quintus 的传统中,元参数被考虑在内。有了你看到的结果。因此,您无法直接比较同一模块中同一元谓词的两个实现。还有其他方法最值得注意的是IFECLiPSe,它们不会通过冒号更改调用上下文。这有优点也有缺点。最好是逐个比较它们。

这是最近的一个案例。以lambda以及如何将它们放入 SICStus、SWIECLiPSe中的模块中。

至于 Quintus/SICStus/YAP/SWI 模块系统,我宁愿以最保守的方式使用它。那是:

  • 没有明确的限定,将中缀:视为内部的东西

  • 干净、可检查的元声明 - 故意插入一个未定义的谓词,只是为了查看交叉引用是否能够检测到问题(在 SWI 中是checkmake)。

  • 使用公共子集,避免许多花里胡哨 - 有许多善意的扩展......

  • 以行人的方式做更多通用的事情:通过添加适当的模块并添加虚拟定义来重新导出。类似地,不是重命名,而是从接口模块导入东西。

  • 请始终注意,模块系统固有地存在一些限制。无论你如何扭转或转动它。没有完全无缝的模块系统,模块的目的就是分离代码和关注点。


1:准确地说,SICStus 对 Quintus 模块的改编确实只在声明中包含:了模块敏感参数。meta_predicate整数0..9对于高阶编程非常重要,call/N直到大约 20 年后才在 2011-03-08 发布的 4.2.0中引入。

于 2015-08-21T16:03:27.633 回答