如何在Prolog中为同一个原子有两个名称?

Ram*_*ete 6 prolog

我想在Prolog中为同一个原子有两个名称:

player(thomas).
player(william).
teamOfPlayer(thomas, redSocks).
teamOfPlayer(william, redSocks).
tom :- thomas.
will :- william.

teamOfPlayer(will, X).
Run Code Online (Sandbox Code Playgroud)

我希望能够使用“ william”原子和“ will”原子来引用William。

我知道我可以使用函子来定义昵称:

nick(tom, thomas).
nick(will, william).
Run Code Online (Sandbox Code Playgroud)

然后,

nick(tom,X), teamOfPlayer(X, Y).
Run Code Online (Sandbox Code Playgroud)

但我想避免所有这些冗长的内容。

Cap*_*liC 5

特定于实现的设施可用于此目的-以及更多。确实,鉴于身份是逻辑的“核心”,重写规则以适合不同的识别策略并不是一个普遍的问题。

在SWI-Prolog中,您可以使用扩展钩子,更具体地说,是goal_expansion / 2。

在您的模块中,在文件末尾附近添加(不过只是一个约定)

:- multifile user:goal_expansion/2.
user:goal_expansion(will, william).
user:goal_expansion(tom, thomas).
Run Code Online (Sandbox Code Playgroud)

编辑

抱歉,我没有调试我的建议,事实证明这是不正确的。可能的更正可能是:

:- multifile user:goal_expansion/2.
user:goal_expansion(will, william).
user:goal_expansion(tom, thomas).
Run Code Online (Sandbox Code Playgroud)

我们可以使重载规则更通用,但是问题深深扎根于语言核心。原子具有身份的基本属性(从关系数据模型的角度来看),然后我们只能在特定的上下文中“超载”原子。


G_V*_*G_V 0

你可以定义某物是否是另一物

player(tom) :- !.
player(thomas) :- player(tom), !.
Run Code Online (Sandbox Code Playgroud)

现在 Prolog 可以看到,如果玩家被命名为thomastom,则目标已达到,因此他们被视为同一个人。

不过,您的第一个解决方案是更可取的,因为它nick(tom,X), teamOfPlayer(X, Y).不太具体,因此更具可扩展性并且更易于维护,因为您不更改现有代码,而只是向知识库添加新事实。

通过定义这两个规则,您可以为 Prolog 提供两种回答 X 的方法。

%is X a member of team Y?
isPartOfTeam(X,Y) :- teamOfPlayer(X,Y).
isPartOfTeam(X,Y) :- nick(X, Z), teamOfPlayer(Z, Y).
Run Code Online (Sandbox Code Playgroud)

通过定义这些一般规则,可以通过直接在事实中找到团队teamOfPlayer(X,Y)或尝试为 X 的特定实例定义的每个昵称来解决 X 。这就是 Prolog 的威力所在。你可以为一个人拥有 10000 个昵称,Prolog 将通过一个称为回溯到选择点的过程,通过上面定义的这两个简单规则来检查所有昵称。