最近这类问题被问了很多(我猜你的教授都分享笔记或其他东西),所以浏览最近的历史可能对你很有帮助。例如,我想到了这个。
您的代码非常广泛。这就是你想要做的:
attribute(Subject, Object) :-
Fact =.. [Object, Subject],
assertz(Fact).
使用它的工作方式如下:
?- attribute(man, tall).
true.
?- tall(X).
X = man.
所以,关于这段代码,你应该注意以下几点:
- 我们使用
=../2
“univ”运算符从列表构建结构。这是从一些原子创建事实的唯一方法。
- 我已经交换了主语和宾语,因为换一种方式几乎肯定不是你想要的。
- 您想要的谓词是
assertz/1
or asserta/1
, not assert/2
。末尾的 a 和 z 只是告诉 Prolog 你想要在数据库的开头还是结尾的事实。
根据查看您的代码,我认为您需要摆脱很多包袱才能使用 Prolog 提高工作效率。
- Prolog 谓词不返回值。所以
assert(term_to_atom(...
甚至不在正确的轨道上,因为您似乎认为这term_to_atom
会“返回”一个值,并且它会assert
像函数式或命令式语言一样被替换到调用中。Prolog 的工作原理与此完全不同。
- 我不确定为什么您的
term_to_atom
谓词中有一个空变量。我认为你这样做是为了满足谓词的数量,但是除非你有一个基本术语和一个变量,否则这个谓词是毫无用处的。
- 有一个
assert/2
,但它不会做你想要的。应该清楚为什么 assert 通常只接受一个参数。
- Prolog 的事实应该是这样
property(subject...)
的。构造事实然后查询它们并不容易,这是您必须使用man(tall)
. 你想说的是有一个属性,个子高,man
满足。
我强烈建议您在此时备份并阅读一些基本的 Prolog 教程。如果你试图向前推进,你只会迷失更多。
编辑:针对您的评论,我不确定您想要多通用。在您处理中间有 [is,a] 的 4 项列表的基本情况下,这就足够了:
build_fact([Subject,is,a,Object], is_a(Subject, Object)).
如果要隔离第一个和最后一个并创建事实,则必须再次使用 univ:
build_fact([Subject|Rest], Fact) :-
append(PredicateAtoms, [Object], Rest),
atomic_list_concat(PredicateAtoms, '_', Predicate),
Fact =.. [Predicate, Subject, Object].
不确定您是否愿意接受最终会出现的文章(“a”,“the”):
?- build_fact([john,could,be,a,man], Fact).
Fact = could_be_a(john, man)