可以用op/3把任何谓词定义为操作符,每个操作符有不同的优先权值,从1到1200。当某句中有多个操作符时,优先权高的将先被考虑,优先权值越小优先权越高。
Prolog操作符有三种形式,其结合性如下:
中缀(infix):例如3+4
xfx 没有结合性
xfy 从右向左
yfx 从左向右
前缀(prefix):例如-7
fx 没有结合性
fy 从右向左
后缀(postfix):例如8f
xf 没有结合性
yf 从右向左
op/3需要三个参数,分别是:优先权、结合性、操作符名称。
其实Prolog程序的子语句也是使用操作符书写的Prolog数据结构。这里的操作符是”:-“,它是中缀操作符,有两个参数。
:-(Head, Body).
Body也是由操作符书写的数据结构。这里的操作符为”,”,它表示并且的意思,所以Body的形式如下:
,(goal1, ,(goal2,,goal3))
好像看不明白,操作符”,”与分隔符”,”无法区别,所以我们就是用”&”来代替操作符”,”,于是上面的形式就变成了下面这个样子了。
&(goal1, &(goal2, & goal3))
下面的两种形式表达的意思是相同的。
head :- goal1 & goal2 & goal3.
:-(head, &(goal1, &(goal2, & goal3))).
实际上是下面的形式:
head :- goal1 , goal2 , goal3.
:-(head, ,(goal1, ,(goal2, , goal3))).
下面用操作符改写一下roomlist:
%swipl -s operator.pl %Hansen %动态函数声明 :-dynamic here/1. :-dynamic is_in/2. :-dynamic in_bag/1. :-dynamic take_thing/2. :-dynamic put_thing/2. %定义操作符 :-op(100,fx,is_room). :-op(101,xfx,is_in). :-op(101,fx,in_bag). :-op(101,fx,move). :-op(101,fx,eat). :-op(101,f,look). %房间定义 room(X):- is_room List,member(X,List). is_room [kitchen,office,hall,diningroom,cellar]. %门定义 door(X,Y):- door_list(List),member([X,Y],List). door_list([[office, hall],[kitchen, office],[hall, diningroom],[kitchen, cellar],[diningroom, kitchen]]). %规则:有门的两个房间是相通的 connect(X,Y):- door(X,Y). connect(X,Y):- door(Y,X). %物品在哪个房间 location(X,Y):- List is_in Y, member(X, List). [apple, broccoli, crackers] is_in kitchen. [desk, computer] is_in office. [flashlight, envelope] is_in desk. [stamp, key] is_in envelope. [] is_in hall. [] is_in diningroom. [washingmachine] is_in cellar. [nani] is_in washingmachine. %房间减少物品 take_thing(Thing, Place):- retract(List is_in Place), delete(List,Thing,ThingsLeft), asserta(ThingsLeft is_in Place). %房间增加物品 put_thing(Thing, Place):- retract(List is_in Place), asserta([Thing|List] is_in Place). %背包有哪些物品 bag(X):-in_bag List, member(X, List). in_bag [tourch]. %背包增加物品 bag_in(Thing):- retract(in_bag List), asserta(in_bag [Thing|List]). %背包减少物品 bag_out(Thing):- retract(in_bag List), delete(List,Thing,ThingsLeft), asserta(in_bag ThingsLeft). %哪些物品可以吃 edible(X):- member(X,[apple,crackers,broccoli]). %当前位置 here(hall). %房间之间移动 move(Place):- can_go(Place),retract(here(X)), asserta(here(Place)). can_go(Place):- here(X), connect(X, Place). can_go(Place):- write('You can''t go to '),write(Place),write(' from here.'), nl, fail. %拿起物品 take(X):- can_take(X), here(Place), take_thing(X,Place), bag_in(X), write(X), write(' taken.'), nl. can_take(Thing):- here(Place), location(Thing, Place). can_take(Thing):- write('There is no '), write(Thing), write(' here.'), nl, fail. %放下物品 put(X):- can_put(X), here(Place), bag_out(X), put_thing(X,Place), write(X), write(' put.'), nl. can_put(Thing):- bag(Thing). can_put(Thing):- write('There is no '), write(Thing), write(' in your bag.'), nl, fail. %房间物品列表 list_things(Place):- location(X, Place),tab(2),write(X),nl,fail. list_things(_). %与Place相连的房间 list_connections(Place):- connect(Place, X),tab(2),write(X),nl,fail. list_connections(_). %持有物品列表 list_bag(Thing):- bag(X),tab(2),write(X),nl,fail. list_bag(_). %吃东西 eat(Thing):- can_eat(Thing), bag_out(Thing), write(Thing), write(' eaten. Yummy!'). can_eat(Thing):- bag(Thing), edible(Thing). can_eat(Thing):- not(bag(Thing)), write('There is no '), write(Thing), write(' in your bag.'), nl, fail. can_eat(Thing):- bag(Thing), write('You can''t eat the '), write(Thing), write('.'), nl, fail. %查看房间情况 look :- here(Place), write('You are in the '), write(Place), nl, write('You can see:'),nl,list_things(Place), write('You can go to:'), nl, list_connections(Place), write('You have:'),nl,list_bag(Thing). %帮助 game :- write('Look around: look/0'),nl, write('Move around: move/1'),nl, write('Take something: take/1'),nl, write('Eat something: eat/1').