欢迎来到序言!我很高兴你给它一个镜头,我希望你发现它能够很好地发挥你的想象力,因为你似乎有很多!
您在这里为Prolog使用了很多奇怪的术语。我不清楚你的意思是“帧”或“节点”或“提取”,我敢肯定你正在使用“咨询”的方式。我不知道这是因为该教程是为SICStus编写的,还是仅仅是通常的混淆。我通常也不会想到在Prolog中做继承,但是我认为其中的部分我确实了解。所以我希望你会一直玩,我们会看看我是否能够回答你的问题。
第一件事第一件事。这不是一个大问题,但平均分数应该这样实施:
avg_score(Z) :-
student(jack, X),
student(jill, Y),
Z is (X + Y)/2. % <-- note the use of 'is' instead of '='
这是一个常见的初学者错误。 Prolog不会默认评估代数,所以当你说出类似(X + Y)/2
的东西时,你所做的只是建立一个表达式,与div(plus(X, Y), 2)
没有什么不同。一个区别是,is
知道如何评估代数表达式,如(X + Y)/2
但不是div(plus(X, Y), 2)
。 (我提前警告你,你会发现序言使许多更有意义,如果你开始使用clpfd
从一开始,并使用#=
代替is
)
没有,什么是无用的约avg_score
,当然,其中jack
和jill
被嵌入其中。有一天,你可能会想要计算你所有学生的平均分数。首先,让我们计算平均值:
average(L, Average) :-
sum(L, Sum),
length(L, Length),
Average is Sum/Length.
% this is overly complex because I wanted to show you
% the tail recursive version
sum(L, Sum) :- sum(L, 0, Sum).
sum([], Sum, Sum).
sum([X|Xs], Acc, Sum) :- Acc1 is X + Acc, sum(Xs, Acc1, Sum).
现在,我们可以得到所有的学生的平均是这样的:
avg_score(Z) :-
findall(X, student(_, X), Scores),
average(Scores, Z).
我不知道发生,如果这涉及到你的要求或不是,但似乎它可能有帮助,所以它就是这样。
当然,另一种可能性是参数化的东西。我们可以采取的原代码,并通过学生将其参数化:
avg_score(Student1, Student2, Z) :-
student(Student1, X),
student(Student2, Y),
Z is (X + Y)/2.
这似乎是它可能是更相关的查询动物寓言。与其询问attack(X)
,你会问attack(fire_warrior, X)
。
当你对Prolog很陌生时,我不想送你到Logtalk,但我怀疑它可能会有你想要的一些答案。它在处理继承方面非常出色,而且Prolog可能不是。但它可能是一个很大的转移。举例来说,你可以处理继承链查询攻击统计是这样的:
% this is the inheritance tree
parent_class(character, base).
parent_class(npc, character).
parent_class(enemy, npc).
parent_class(red_faction, enemy).
parent_class(blue_faction, enemy).
parent_class(fire_warrior, red_faction).
parent_class(water_consort, blue_faction).
% these are the attack bonuses
attack_bonus(base, 0).
attack_bonus(red_faction, 1.5).
attack_bonus(blue_faction, 1).
calc_attack_bonus(X, Bonus) :-
attack_bonus(X, Bonus), !.
calc_attack_bonus(X, Bonus) :-
\+ attack_bonus(X, Bonus),
parent_class(X, Parent),
calc_attack_bonus(Parent, Bonus).
这似乎是一些基本的查询工作:
?- calc_attack_bonus(fire_warrior, Bonus).
Bonus = 1.5.
?- calc_attack_bonus(character, Bonus).
Bonus = 0.
我不知道,如果你想这种行为或不:
?- calc_attack_bonus(tree, Bonus).
false.
很容易解决,如果没有(如果parent_class
失败,统一用0奖金,否则易复发)。
然而,这不是所有可扩展的。更可扩展的方法可能是这样的:
% these are the attack bonuses
attribute(attack_bonus, base, 0).
attribute(attack_bonus, red_faction, 1.5).
attribute(attack_bonus, blue_faction, 1).
% base stats
attribute(base_stat, character, 8.0).
attribute(level, fire_warrior, 1.0).
现在我们可以写我们需要没有很多痛苦的规则:
calc_attribute(X, Attribute, Value) :-
attribute(X, Attribute, Value), !.
calc_attribute(X, Attribute, Value) :-
\+ attribute(X, Attribute, Value),
parent_class(X, Parent),
calc_attribute(Parent, Attribute, Value).
而且现在的攻击变得容易:
attack(X, Value) :-
calc_attribute(X, attack_bonus, Bonus),
calc_attribute(X, base_stat, Base),
calc_attribute(X, level, Level),
Value is (Level + Base) * Bonus.
我们需要进一步概括一下,以便我们可以写出compute
的地方,因为理想情况下,我们想要说些类似compute(fire_warrior, attack, Value)
的东西。为了实现这一点,我们需要知道attack_bonus
与attack
有关,我们不知道。让我们重组attribute
一点:
% these are the attack bonuses
attribute(base, bonus(attack), 0).
attribute(red_faction, bonus(attack), 1.5).
attribute(blue_faction, bonus(attack), 1).
% base stats
attribute(character, base_stat, 8.0).
attribute(fire_warrior, level, 1.0).
现在我们正在做饭:
compute(X, Attribute, Value) :-
calc_attribute(X, bonus(Attribute), Bonus),
calc_attribute(X, base_stat, Base),
calc_attribute(X, level, Level),
Value is (Level + Base) * Bonus.
看哪:
?- compute(fire_warrior, attack, Value).
Value = 13.5.
我希望这是你想要的。 :)
大编辑
为了好玩,我想我会看到这会变成什么样子Logtalk,用于Prolog的面向对象的扩展语言。我是非常新 Logtalk,所以这可能或可能不是一个好方法,但它做了“做伎俩”,让我们看看它是否更符合你想要的。首先,基本对象:
:- object(base).
:- public(base_stat/1).
:- public(attack/1).
:- public(bonus/2).
:- public(level/1).
:- public(compute/2).
bonus(attack, 0).
base_stat(0).
level(0).
compute(Attribute, Value) :-
::bonus(Attribute, Bonus),
::base_stat(Base),
::level(Level),
Value is (Level + Base) * Bonus.
:- end_object.
这基本上是定义我们要存储每个东西的事实,以及如何计算你感兴趣的属性接下来,我们建立对象层次:
:- object(character, extends(base)).
base_stat(8.0).
:- end_object.
:- object(npc, extends(character)).
:- end_object.
:- object(enemy, extends(npc)).
:- end_object.
:- object(red_faction, extends(enemy)).
bonus(attack, 1.5).
bonus(speed, 1.25).
bonus(defense, 0.25).
:- end_object.
:- object(blue_faction, extends(enemy)).
bonus(attack, 1).
bonus(speed, 1).
bonus(defense, 1).
:- end_object.
:- object(fire_warrior, extends(red_faction)).
level(1.0).
holding(nothing).
:- end_object.
:- object(water_consort, extends(blue_faction)).
level(1.0).
holding(nothing).
:- end_object.
现在用这是一个很值得扣:
?- fire_warrior::compute(attack, X).
X = 13.5.
?- water_consort::compute(attack, X).
X = 9.0.
我希望这有助于!
哇,开始是一个有趣的阅读本身,运行轨迹以查看“谓词(list [],变量,变量)”查询是如何一直工作到做出更精炼的查询。 – 2013-03-23 16:58:12
我正在研究Logtalk的建议,它看起来像今晚读的地狱。看到你的例子,我可以看到它只是我需要的插件和编程风格。你可以清楚地看到这些关系,并且当我查看我的语义图时,我已经可以了解它的全貌。您可能无法理解Frame是什么,但Logtalk也可以很好地将视觉方面转换为代码。我很高兴今晚进一步了解这一点。 – 2013-03-23 17:05:42
对于这种解释,你应该得到一杯好喝的饮料,因为如果没有这些例子,我就不会看到相关性。 – 2013-03-23 17:06:05