我想在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)
但我想避免所有这些冗长的内容。
特定于实现的设施可用于此目的-以及更多。确实,鉴于身份是逻辑的“核心”,重写规则以适合不同的识别策略并不是一个普遍的问题。
在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)
我们可以使重载规则更通用,但是问题深深扎根于语言核心。原子具有身份的基本属性(从关系数据模型的角度来看),然后我们只能在特定的上下文中“超载”原子。
你可以定义某物是否是另一物
player(tom) :- !.
player(thomas) :- player(tom), !.
Run Code Online (Sandbox Code Playgroud)
现在 Prolog 可以看到,如果玩家被命名为thomas或tom,则目标已达到,因此他们被视为同一个人。
不过,您的第一个解决方案是更可取的,因为它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 将通过一个称为回溯到选择点的过程,通过上面定义的这两个简单规则来检查所有昵称。
| 归档时间: |
|
| 查看次数: |
180 次 |
| 最近记录: |