gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 02:34:10 25 4
gpt4 key购买 nike

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

我基本上有两个文件:

  • 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 我的其他文件这样的谓词,除非它说:

Local definition of user:justAfter/2 overrides weak import from module

如何使用从模块导入的谓词,而不是重新定义它?

最佳答案

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

----- 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).

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

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

我们得到:

?- [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.

虽然这些是警告而不是错误,但调用inside/3谓词不会给你你想要的东西:

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

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

?- 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.

跟踪清楚地表明“状态”谓词是在错误上下文中调用的。

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

----- 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).

并从state中删除(或注释掉)子句objectOfEvent(injEvent, food).。保存并重新加载并重试查询将为您提供:

?- {*}.   % 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), ...]).

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

关于object - Prolog:覆盖谓词和使用它之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52563407/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com