我最近发现了Prolog语言,并一直在进行基础练习。我目前正在建立有关mammals
,birds
和reptiles
等动物类的数据库,我想通过在动物内部进行大小比较来扩展数据库,但不确定如何做。
这是我的数据库。
warm_blooded(bat).
warm_blooded(penguin).
cold_blooded(crocodile).
has_fur(bat).
has_feathers(penguin).
has_scales(crocodile).
gives_birth_live(bat).
lays_eggs(penguin).
lays_eggs(crocodile).
produces_milk(bat).
has_lungs(crocodile).
has_lungs(bat).
has_lungs(penguin).
%% if the being belongs to the mammalai class ,mammalia being the scientific word for mammal
mammalia(X) :-
warm_blooded(X),
produces_milk(X),
(
has_fur(X)
;
gives_birth_live(X)
),
format('~w ~s mammal ~n', [X, "is a"]).
%% if the being belongs to the aves class aves being the scientific word for bird
aves(X) :-
warm_blooded(X),
has_feathers(X),
lays_eggs(X),
has_lungs(X),
format('~w ~s bird ~n', [X, "is a"]).
%% if the being belongs to the reptillia class(reptillia being the scientific word for reptile
reptillia(X) :-
cold_blooded(X),
lays_eggs(X),
has_scales(X),
has_lungs(X),
format('~w ~s reptile ~n', [X, "is a"]).
我尝试在参数中添加大小,但一直收到编译错误。我想要一个输出,用户可以确定彼此比较时哪个动物更大。
答案 0 :(得分:2)
一种简单有效的方法是将大小事实与每只动物相关联。
size(bat,1).
size(penguin,2).
size(crocodile,3).
然后添加一个带有两个子句的谓词,以选择两个动物中较大的一个。
larger(A,B,A) :-
size(A,S1),
size(B,S2),
S1 > S2.
larger(A,B,B) :-
size(A,S1),
size(B,S2),
S2 >= S1.
示例:
?- larger(penguin,crocodile,X).
X = crocodile.
?- larger(penguin,bat,X).
X = penguin ;
false.
?- larger(bat,bat,X).
X = bat.
请注意,对于第二个动物较小的示例,它将尝试第一个子句并成功,但是随后有一个选择点,因此尝试第二个子句并失败。这是纯解决方案。
如果您想通过切割来避免选择点不纯净,则可以执行以下操作
larger_2(A,B,A) :-
size(A,S1),
size(B,S2),
S1 > S2,
!.
larger_2(A,B,B) :-
size(A,S1),
size(B,S2),
S2 >= S1,
!.
示例:
?- larger_2(penguin,crocodile,X).
X = crocodile.
?- larger_2(penguin,bat,X).
X = penguin.
?- larger_2(bat,bat,X).
X = bat.
丹尼尔·里昂斯(Daniel Lyons)指出的另一种方法是使用->/2
larger_3(A,B,Larger) :-
size(A,SA),
size(B,SB),
(
SA > SB
->
Larger = A
;
Larger = B
).
此变体不仅仅是->/2
的一个运算符,而是->/2和;2的组合。
这也不会留下选择点,并且是不纯正的,因为它也使用剪切(!
)。使用listing/1,我们可以在Prolog中看到实现。
?- listing('->'/2).
:- meta_predicate 0->0.
system:A->B :-
call(( A
-> B
)).
true.
?- listing(;/2).
:- meta_predicate 0;0.
system:A:B;A:C :- !,
call(A:(B;C)).
system:A:B;C:D :-
call(A:(B;C:D)).
true.
请注意削减!
。
SWI-Prolog documentation中指出了两个操作员如何协同工作。
The combination ;/2 and ->/2 acts as if defined as:
If -> Then; _Else :- If, !, Then.
If -> _Then; Else :- !, Else.
If -> Then :- If, !, Then.
关于->/2
与;/2
一起使用的另一点要注意的是,许多Prolog程序员之间的语法布局是结合使用()
和偏移运算符{{1 }}和->/2
,以使;2
脱颖而出。
;
当将(
% condition
->
% true
;
% false
)
用作OR运算符并且不偏移;
时,在对源代码进行快速扫描时通常会被忽略,因为它被视为逗号;
,
。
还要注意
之后没有;
或.
,
和
SA > SB
和
Larger = A
但是最后需要一个运算符,
Larger = B