Prolog:覆盖谓词和使用它之间的区别

2024-03-20

我觉得自己真的很愚蠢,感觉自己错过了一些东西。

我基本上有两个文件:

  • module.pl通用逻辑规则(可重用)
  • state.pl一个针对当前场景

在模块文件中(module.pl)我已经声明:

inside(Food,Eater,T) :-
    isTime(T),
    injestEvent(InjEvent),
    justAfter(T,InjEvent),
    actorOfEvent(InjEvent, Eater),
    objectOfEvent(InjEvent, Food).

Q1)我必须用单例变量(在同一个文件中)声明所有其他谓词,只是为了停止module.pl抱怨它们不存在:

isTime(_T).
justAfter(_Time,_Event).

actorOfEvent(_Event, _ActorOfEvent).
objectOfEvent(_Event,_ActorOfEvent).

是对的吗?

Q2)我不能使用这些谓词justAfter/2我的另一个文件没有说:

user:justAfter/2 的本地定义覆盖模块的弱导入

我怎么能够use我从模块导入的谓词,而不是重新定义它?


Prolog 模块旨在隐藏辅助谓词。它们不提供允许将谓词声明与谓词定义分开的接口概念。这就是为什么如果您导出未定义的谓词,编译器会抱怨的原因。根据您的描述,我假设您尝试过类似的操作:

----- module.pl -----
:- module(module, [
    inside/3, isTime/1, injestEvent/1, justAfter/2, actorOfEvent/2, objectOfEvent/2
]).

inside(Food,Eater,T) :-
    isTime(T),
    injestEvent(InjEvent),
    justAfter(T,InjEvent),
    actorOfEvent(InjEvent, Eater),
    objectOfEvent(InjEvent, Food).
---------------------

结果是:

?- [module].
ERROR: Exported procedure module:justAfter/2 is not defined
ERROR: Exported procedure module:isTime/1 is not defined
ERROR: Exported procedure module:injestEvent/1 is not defined
ERROR: Exported procedure module:objectOfEvent/2 is not defined
ERROR: Exported procedure module:actorOfEvent/2 is not defined
true.

您尝试通过添加本地定义来解决此错误。但这只会导致你描述的第二个问题。当你做类似的事情时:

?- use_module(module).

你导入all导出的谓词module,包括您想要定义的那些state.pl。因此,编译器在加载时会警告您state.pl,该文件正在覆盖这些谓词。例如。和:

----- state.pl -----
isTime(1).
injestEvent(injEvent).
justAfter(1, injEvent).
actorOfEvent(injEvent, eater).
objectOfEvent(injEvent, food).
--------------------

we get:

?- [state].
Warning: /Users/pmoura/Desktop/state.pl:1:
    Local definition of user:isTime/1 overrides weak import from module
Warning: /Users/pmoura/Desktop/state.pl:2:
    Local definition of user:injestEvent/1 overrides weak import from module
Warning: /Users/pmoura/Desktop/state.pl:3:
    Local definition of user:justAfter/2 overrides weak import from module
Warning: /Users/pmoura/Desktop/state.pl:4:
    Local definition of user:actorOfEvent/2 overrides weak import from module
Warning: /Users/pmoura/Desktop/state.pl:5:
    Local definition of user:objectOfEvent/2 overrides weak import from module
true.

虽然这些是warnings而不是错误,调用inside/3谓词will没有给你你想要的:

?- inside(Food,Eater,T).
true.

绑定在哪里?!?让我们跟踪调用以突出显示原因:

?- trace.
true.

[trace]  ?- inside(Food,Eater,T).
   Call: (8) module:inside(_2508, _2510, _2512) ? creep
   Call: (9) module:isTime(_2512) ? creep
   Exit: (9) module:isTime(_2512) ? creep
   Call: (9) module:injestEvent(_2804) ? creep
   Exit: (9) module:injestEvent(_2804) ? creep
   Call: (9) module:justAfter(_2512, _2806) ? creep
   Exit: (9) module:justAfter(_2512, _2806) ? creep
   Call: (9) module:actorOfEvent(_2804, _2510) ? creep
   Exit: (9) module:actorOfEvent(_2804, _2510) ? creep
   Call: (9) module:objectOfEvent(_2804, _2508) ? creep
   Exit: (9) module:objectOfEvent(_2804, _2508) ? creep
   Exit: (8) module:inside(_2508, _2510, _2512) ? creep
true.

跟踪清楚地表明“状态”谓词正在被调用wrong语境。

一个干净的解决方案是使用 Logtalk 对象而不是 Prolog 模块。 Logtalk 扩展了 Prolog 并支持大多数系统,包括 SWI-Prolog。它支持接口/协议作为第一类实体(这解决了您提到的第一个问题),并支持继承和在其使用上下文中调用谓词(这解决了第二个问题)。你可以使用例如

----- common.lgt -----
:- object(common).

:- public([
    inside/3, isTime/1, injestEvent/1, justAfter/2, actorOfEvent/2, objectOfEvent/2
]).

inside(Food,Eater,T) :-
    % call the next predicates in "self", i.e. in the
    % object that received the inside/3 message
    ::isTime(T),
    ::injestEvent(InjEvent),
    ::justAfter(T,InjEvent),
    ::actorOfEvent(InjEvent, Eater),
    ::objectOfEvent(InjEvent, Food).

:- end_object.
----------------------

然后将“状态”表示为:

----- state.lgt -----
:- object(state, extends(common)).

isTime(1).
injestEvent(injEvent).
justAfter(1, injEvent).
actorOfEvent(injEvent, eater).
objectOfEvent(injEvent, food).

:- end_object.
---------------------

快速测试(安装 Logtalk 后):

$ swilgt
...
?- {common, state}.
...
true.

?- state::inside(Food,Eater,T).
Food = food,
Eater = eater,
T = 1.

作为奖励,您可以根据需要定义任意数量的“状态”对象。您还可以拥有默认定义对于“状态”谓词common目的。当“状态”对象不提供特定谓词的定义时,这些将被继承和使用。例如,让我们添加到common该条款:

objectOfEvent(injEvent, drink).

并删除(或注释掉)该条款objectOfEvent(injEvent, food). from state。保存并重新加载并重试查询将为您提供:

?- {*}.   % abbreviation for Logtalk's make
% Redefining object common
...
% Redefining object state
...
true.

?- state::inside(Food,Eater,T).
Food = drink,
Eater = eater,
T = 1.

如果需要,您还可以动态创建新的状态对象,而不是在源文件中定义它们。例如:

?- create_object(s2, [extends(common)], [], [isTime(42), ...]).

This 未必您正在寻找的答案,但这也是最好的答案是使用正确的工具^H^H^H^H 封装机制来完成工作的情况。您的编程模式也是一种非常常见的模式(也是开发 Logtalk 的原因之一)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Prolog:覆盖谓词和使用它之间的区别 的相关文章

  • 如何从对象内部的数组中取出具体的对象呢? (使用 pop() 或其他解决方案)

    我想从 myObj 中的年份中删除 hello5 我使用了 pop 原型 但浏览器控制台返回以下结果 未捕获的类型错误 无法读取未定义的属性 类型 以下是我的问题的示例 您可以尝试并会从控制台看到错误消息 我尝试了很长时间但没有找到任何解决
  • 如何在java中读取和写入对象到文本文件?

    我有一个对象数组 我想将它们写入文本文件中 这样我以后就可以将对象读回到数组中 我该怎么做呢 使用序列化 反序列化不起作用 public static void readdata ObjectInputStream input null t
  • 为什么导入的函数“作为”另一个名称保留其原始 __name__ ?

    Here from os path import exists as foo print foo name we get exists 为什么不 foo 哪个属性会给出 foo 您可以查看import foo as bar只是一个任务 你不
  • 在Windows中启动python时导入模块[重复]

    这个问题在这里已经有答案了 我在 Windows 上使用 python 我正在尝试找到一种在启动 python 时导入一些默认模块的方法 这意味着 当启动python时 一些模块应该已经导入 就像builtins 有什么办法吗 Thanks
  • String类如何重写+运算符?

    为什么在 Java 中 当 String 是一个类时 您可以使用 运算符添加字符串 在里面String java代码我没有找到这个运算符的任何实现 这个概念违反了面向对象吗 我们看一下Java中的以下简单表达式 int x 15 Strin
  • 如何获取当前模块内某个类的所有实例

    我有一个模块foo定义一个类Foo 并实例化该类的多个实例 从其他模块 我可以import foo并获得一个列表Foo实例化的对象 getattr foo f for f in dir f if isinstance getattr foo
  • 对象类和数组 - 为什么它返回“null”? [java]

    我编写了一个小类 它创建一个包含 3 个数组的报表对象 在创建对象时 这些数组用值进行初始化 然而 当我测试该类以查看例如部门数组中的内容时 它会打印出数组元素为空 为什么 class Report declare instance var
  • 如何编写一个函数来测试链接列表是否已排序

    我查看了其他帖子 但没有找到适合我的查询的很好的解决方案 我不想对链接列表进行实际排序 我想看看它是否已排序 我有一个 C 中的链表问题 我被要求编写一个给定链表定义的函数来查看它是否已排序 实现函数 isSorted 如果链表中的值按升序
  • Rails:如何为 ruby​​ 模块编写测试?

    我想知道如何为混合到几个类中的模块编写单元测试 但不太知道如何去做 我是否通过在包含它们的类的测试文件之一中编写测试来测试实例方法 似乎不正确 或者您可以以某种方式将所包含方法的测试保留在特定于模块的单独文件中吗 同样的问题也适用于类方法
  • 在序言中减去或添加列表的列表?

    我对序言相当陌生 正在尝试摆弄列表列表 我很好奇如何添加两个列表列表或减去它们从而得到一个列表列表 如果我有两个列表 可以说 SomeList 1 2 3 4 5 6 7 8 SomeList2 1 2 3 4 5 6 7 8 我该如何添加
  • 为什么模块中的公共函数不可访问

    我有一个由几个有用的小实用程序组成的程序集 其中我有一个包含简单公共功能的模块 Module FishTrackerConfigurations Public Function GetValueOfUseProductId As Boole
  • React 中的 Map 函数(错误:TypeError:e.map 不是函数)

    我想从道具渲染项目 我可以使用初始状态来完成 但不能使用服务器的响应来完成 我的渲染函数 const data this props return div data map item index gt div span item id sp
  • var->myProperty 和 var.myProperty 之间的区别

    我是 Objective C 的新手 我有一些疑问 我发现您可以访问类的属性 例如var gt 我的属性也喜欢那样变量 myProperty 但我不知道2之间有什么区别 我在互联网上搜索了很多 但确实没有找到确凿的答案 抱歉 如果我有拼写错
  • 如何设置“如果对象存在”条件?

    有没有办法检查对象是否存在 我不断收到 需要对象 错误 我知道该对象不存在 如果是这种情况 我想绕过我的代码的一部分 我不知道什么是我没有尝试过的 var codeName document getElementById testCode
  • 具有来自包含器类的静态方法调用的 Ruby 模块

    我需要在模块中定义使用包含该模块的类中的方法的常量 module B def self included base class lt lt base CONST self find end end end class A def self
  • Java 中将对象与 null 进行比较

    我正在尝试验证一个对象是否是null或不 使用以下语法 void renderSearch Customer c System out println search customer rendering gt try if c equals
  • java中引用和对象有什么区别? [复制]

    这个问题在这里已经有答案了 我有类 GUI 所以我可以创建这样的对象 GUI g1 new GUI 和一个像这样的引用变量 GUI g2 现在据我所知 g2 是一个引用变量 它引用 GUI 类 而 g1 是 GUI 类的对象 g1和g2有什
  • excel vba 将 system.collections.hashmap 导入模块

    从我的内心微软 Excel 2010安装我已经打开了Visual Basic 编辑器 选项卡开发工具 gt Visual Basic 在 的里面Visual Basic 编辑器我右键单击进入项目窗口并创建了一个module 插入 gt 模块
  • 将我的数据库类与项目中的其他类一起使用

    我有一个自己编写的自定义数据库类 还有一个用户类和一个站点类 MySQL 类有这样的方法 connect query clean fetch 用户等级 register login logout resetPass 站点类别 updateT
  • Excel VBA 模块在运行时未更新

    我有 2 个模块 主模块在运行时更新另一个模块 并在每次更新时运行该模块 问题是另一个模块在运行时似乎没有更新 它运行第一个模块 因为输出全部根据第一个输入 但运行完成后 我检查了其他模块 它已更新 但输出不符合更新的模块 我已经问过这个问

随机推荐