About neohope

一直在努力,还没想过要放弃...

Prolog101(14)

首先,我们用英文语法分析两个句子:
The dog ate the bone.
The big brown mouse chases a lazy cat.

sentence(句子): 
nounphrase(名词短语), verbphrase(动词短语).  

nounphrase(名词短语): 
determiner(限定词), nounexpression(名词表达式).  
nounphrase (名词短语): 
nounexpression(名词表达式).  

nounexpression(名词表达式):  
noun.  
nounexpression(名词表达式):
adjective(形容词), nounexpression(名词表达式).  

verbphrase(动词短语): 
verb(动词), nounphrase(名词短语).  

determiner(限定词): 
the | a.  

noun(名词): 
dog | bone | mouse | cat.  

verb(动词): 
ate | chases.  

adjective(形容词):  
big | brown | lazy.  

差异表:它由两个相关的表构成,第一个表称为全表,而第二个表称为余表。通常使用‘-’连接这两个表。它的形式是X-Y。

%单个词的判断规则:如果列表的第一个元素是所需的单词,那么余表就是除去第一个单词的表。
%名词
noun([dog|X]-X). 
noun([cat|X]-X). 
noun([mouse|X]-X). 

%动词
verb([ate|X]-X). 
verb([chases|X]-X). 

%形容词
adjective([big|X]-X). 
adjective([brown|X]-X). 
adjective([lazy|X]-X). 

%限定词
determiner([the|X]-X). 
determiner([a|X]-X). 

%短语判断规则
nounphrase(NP-X):- 
determiner(NP-S1), 
nounexpression(S1-X). 

nounphrase(NP-X):- 
nounexpression(NP-X). 
nounexpression(NE-X):- 
noun(NE-X). 

nounexpression(NE-X):- 
adjective(NE-S1), 
nounexpression(S1-X). 

verbphrase(VP-X):- 
verb(VP-S1), 
nounphrase(S1-X).

%语句判断规则:如果能够从列表S的头开始,提取出一个名词短语,其余部分S1,并且能够从S1的头开始,提取出一个动词短语,并且其余部分为空表,那么列表S是一个句子。
sentence(S) :- 
nounphrase(S-S1), 
verbphrase(S1-[]). 

测试一下:

?- sentence([the,lazy,mouse,ate,a,dog]).
true .

?- sentence([the,dog,ate]).
false.

?- sentence([a,big,brown,cat,chases,a,lazy,brown,dog]).
true .

?- sentence([the,cat,jumps,on,the,mouse]).
false.

Prolog101(13)

递归与尾递归:

%需要栈记录中间结果
factorial_1(1,1).
factorial_1(N,F):- 
N > 1,
NN is N - 1,
factorial_1(NN,FF),
F is N * FF.

%不需要记录中间结果
factorial_2(1,F,F). 
factorial_2(N,T,F):- 
N > 1,
TT is N * T,
NN is N - 1,
factorial_2(NN,TT,F).
?- factorial_1(5,X).
X = 120 .

?- factorial_2(5,1,X).
X = 120 .
%用栈记录中间结果
reverse_1([],[]). 
reverse_1([H|T],Rev):- 
reverse_1(T,TR), 
append(TR,[H],Rev).

%借助变量记录中间结果
reverse_2([], Rev, Rev). 
reverse_2([H|T], Temp, Rev) :- 
reverse_2(T, [H|Temp], Rev). 
?- reverse_1([a,b,c,d,e],X).
X = [e, d, c, b, a].

?- reverse_2([a,b,c,d,e],[],X).
X = [e, d, c, b, a].

Prolog101(12)

谓词repeat,相当于循环,根据最后一句语句判断是否退出循环。

sayhi:-
write('What is your name?'),
read(X),write('Hi '),write(X).

sayhito(X):-
write('Hi '),write(X).
do(sayhito(X)):-sayhito(X),!. 

loop_test:-
repeat, 
write('Enter command (end to exit): '), 
read(X), 
write(">>"), 
write(X), 
nl, 
X=end. 

用纯逻辑方法改写一下nani的例子

% a nonassertive version of nani search  

nani :- 
write('Welcome to Nani Search'), 
nl, 
initial_state(State), 
control_loop(State). 

control_loop(State) :- 
end_condition(State). 
control_loop(State) :- 
repeat, 
write('> '), 
read(X), 
constraint(State, X), 
do(State, NewState, X), 
control_loop(NewState). 

% initial dynamic state  
initial_state([ 
here(kitchen), 
have([]), 
location([ 
kitchen/apple, 
kitchen/broccoli, 
office/desk, 
office/flashlight, 
cellar/nani ]), 
status([ 
flashlight/off, 
game/on]) ]). 

% static state  
rooms([office, kitchen, cellar]). 
doors([office/kitchen, cellar/kitchen]). 

connect(X,Y) :- 
doors(DoorList), 
member(X/Y, DoorList). 
connect(X,Y) :- 
doors(DoorList), 
member(Y/X, DoorList). 

% list utilities  
member(X,[X|Y]). 
member(X,[Y|Z]) :- member(X,Z). 

delete(X, [], []). 
delete(X, [X|T], T). 
delete(X, [H|T], [H|Z]) :- delete(X, T, Z). 

% state manipulation utilities
get_state(State, here, X) :- 
member(here(X), State). 
get_state(State, have, X) :- 
member(have(Haves), State), 
member(X, Haves). 
get_state(State, location, Loc/X) :- 
member(location(Locs), State), 
member(Loc/X, Locs). 
get_state(State, status, Thing/Stat) :- 
member(status(Stats), State), 
member(Thing/Stat, Stats). 

del_state(OldState, [location(NewLocs) | Temp], location, Loc/X):- 
delete(location(Locs), OldState, Temp), 
delete(Loc/X, Locs, NewLocs). 

add_state(OldState, [here(X)|Temp], here, X) :- 
delete(here(_), OldState, Temp). 
add_state(OldState, [have([X|Haves])|Temp], have, X) :- 
delete(have(Haves), OldState, Temp). 
add_state(OldState, [status([Thing/Stat|TempStats])|Temp], status, Thing/Stat) :- 
delete(status(Stats), OldState, Temp), 
delete(Thing/_, Stats, TempStats). 

% end condition  
end_condition(State) :- 
get_state(State, have, nani), 
write('You win'). 

end_condition(State) :- 
get_state(State, status, game/off), 
write('quitter'). 

% constraints and puzzles together  
constraint(State, goto(cellar)) :- 
!, can_go_cellar(State). 
constraint(State, goto(X)) :- 
!, can_go(State, X). 
constraint(State, take(X)) :- 
!, can_take(State, X). 
constraint(State, turn_on(X)) :- 
!, can_turn_on(State, X). 
constraint(_, _). 

can_go(State,X) :- 
get_state(State, here, H), 

connect(X,H). 
can_go(_, X) :- 
write('You can''t get there from here'), 
nl, fail. 

can_go_cellar(State) :- 
can_go(State, cellar), 
!, cellar_puzzle(State). 

cellar_puzzle(State) :- 
get_state(State, have, flashlight), 
get_state(State, status, flashlight/on). 
cellar_puzzle(_) :- 
write('It''s dark in the cellar'), 
nl, fail. 

can_take(State, X) :- 
get_state(State, here, H), 
get_state(State, location, H/X). 
can_take(State, X) :- 
write('it is not here'), 
nl, fail. 

can_turn_on(State, X) :- 
get_state(State, have, X). 
can_turn_on(_, X) :- 
write('You don''t have it'), 
nl, fail. 

% commands  
do(Old, New, goto(X)) :- goto(Old, New, X), !. 
do(Old, New, take(X)) :- take(Old, New, X), !. 
do(Old, New, turn_on(X)) :- turn_on(Old, New, X), !. 
do(State, State, look) :- look(State), !. 
do(Old, New, quit) :- quit(Old, New). 
do(State, State, _) :- 
write('illegal command'), nl. 

look(State) :- 
get_state(State, here, H), 
write('You are in  '), write(H), nl, 
write('You can see'), list_things(State, H), nl,
write('You have'), list_bag(State, H), nl,
write('You can go'), list_rooms(H), nl. 

list_things(State, H) :- 
get_state(State, location, H/X), 
tab(2), write(X), 
fail. 
list_things(_, _). 

list_rooms(H) :- 
connect(X,H),tab(2),write(X),fail.
list_rooms(_).

list_bag(State, H) :- 
get_state(State, have, X), 
tab(2), write(X), 
fail. 
list_bag(_, _). 

goto(Old, New, X) :- 
add_state(Old, New, here, X), 
look(New). 

take(Old, New, X) :- 
get_state(Old, here, H), 
del_state(Old, Temp, location, H/X), 
add_state(Temp, New, have, X). 

turn_on(Old, New, X) :- 
add_state(Old, New, status, X/on). 

quit(Old, New) :- 
add_state(Old, New, status, game/off).

试一下

?- nani().
Welcome to Nani Search
> look.
You are in  kitchen
You can see  apple  broccoli
You have
You can go  office  cellar
> |: take(apple).
> |: take(broccoli).
> |: goto(office).
You are in  office
You can see  desk  flashlight
You have  broccoli  apple
You can go  kitchen
> |: take(desk).
> |: take(flashlight).
> |: goto(kitchen).
You are in  kitchen
You can see
You have  flashlight  desk  broccoli  apple
You can go  office  cellar
> |turn_on(flashlight).
> |: goto(cellar).
You are in  cellar
You can see  nani
You have  flashlight  desk  broccoli  apple
You can go  kitchen
> |: take(nani).
You win
true .

Prolog101(11)

使用Prolog时,有时需要人为的终止回溯,此时会用到谓词cut,使用符号!来表示。

data(one).  
data(two). 
data(three).

cut_test_a(X) :- data(X).
cut_test_a('last clause').

cut_test_b(X) :- data(X), !.  
cut_test_b('last clause').

cut_test_c(X,Y) :- data(X), !, data(Y).
cut_test_c('last clause'). 

来测试一下

1- cut_test_a(X), write(X), nl, fail. 
one
two
three
last clause
false.

2- cut_test_b(X), write(X), nl, fail. 
one
false.

3- cut_test_c(X,Y), write(X-Y), nl, fail.
one-one
one-two
one-three
false.

此外,可以用not谓词判断条件是否成立

not(X) :- call(X), !, fail. 
not(X)

下面两种方式是等效的:

have(apple).

eat():-
write('yummy...').

eat_fruit_a(X):- 
have(X), 
!,
eat().

eat_fruit_b(X):-  not(can_not_eat(X)),eat().
can_not_eat(X):-  
not(have(X)).

eat_fruit_c(X):-  can_eat(X),eat().
can_eat(X):- have(X).
can_eat(X):- fail.
1- eat_fruit_a(apple).
yummy...
true.

2- eat_fruit_a(pear).
false.

3- eat_fruit_b(apple).
yummy...
true.

4- eat_fruit_b(pear).
false.

5- eat_fruit_c(apple).
yummy...
true .

6- eat_fruit_c(pear).
false.

Prolog101(10)

可以用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').

从BootCamp中提取HFS驱动

一、说明:
1、如果你是MAC,那直接安装Bootcamp就好了,别瞎折腾

2、如果你只想用这个驱动,来这里下载https://forums.macrumors.com/threads/apple-hfs-windows-driver-download.1368010/

3、即使你折腾成功了,也是只读,无法写入

4、Bootcamp的版本是通过下面的条件划分的
A、MAC硬件版本
B、Windows操作系统版本(win7、win8、win10、x86、x64)
C、发布版本
从而,直接查找Bootcamp,本身就成了一件很痛苦的事情

5、Bootcamp的HFS驱动文件的默认安装位置为
C:\Windows\System32\drivers\AppleHFS.sys
C:\Windows\System32\drivers\AppleMNT.sys
而文件系统驱动是与MAC硬件版本无关的,所以我们只需要考虑B、C两个问题就好了

二、然后说HFS驱动提取的方式:
1、按上面所说的,驱动提取只需要考虑Windows操作系统版本和Bootcamp发布版本就可以了,是不需要考虑MAC硬件版本的
2、下载后,解压文件
3、将AppleHFS.sys、AppleMNT.sys拷贝出来
4、备份注册表(这一步一般来说是可以省掉的)
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\AppleHFS
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\AppleMNT

一般来说用下面的文件进行安装和卸载就好了:
Add_AppleHFS.reg

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\AppleHFS]
"Type"=dword:00000002
"ErrorControl"=dword:00000001
"Start"=dword:00000000
"Group"="File System"

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\AppleMNT]
"Group"="System Bus Extender"
"Type"=dword:00000001
"ErrorControl"=dword:00000001
"Start"=dword:00000000

Remove_AppleHFS.reg

Windows Registry Editor Version 5.00

[-HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\AppleHFS]

[-HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\AppleMNT]

5、这样驱动提取就完成了

三、HFS驱动的安装方式:
1、一定要核对windows版本与驱动提取的版本信息是一致的才可以(win7、win8、win10、x86、x64)
2、将驱动拷贝到指定路径
C:\Windows\System32\drivers\AppleHFS.sys
C:\Windows\System32\drivers\AppleMNT.sys
3、双击Add_AppleHFS.reg
4、重启即可

四、HFS驱动的卸载方式:
1、双击Remove_AppleHFS.reg
2、重启
3、删除驱动文件
C:\Windows\System32\drivers\AppleHFS.sys
C:\Windows\System32\drivers\AppleMNT.sys

五、兼容Win10方式:
1、按上面的方式安装驱动
2、打开磁盘管理器,从磁盘0的第一个卷,一直数到你想挂在的HFS卷,记录卷的序号,比如我有几块硬盘,我想挂载的卷是第10个卷(要注意,没有挂载的卷也是要计算的)
3、修改注册表

#位置
HKEY_LOCAL_MACHINE/system/CurrentControlSet/Control/Session Manager/DOS Devices/
#新建String类型的键值对
#左边的Key就是你想挂在的盘符,比如
#N:
#右边的Value就是卷的序号
#\Device\HarddiskVolume序号
#比如你是第10个卷,那就是
#\Device\HarddiskVolume10

4、重启,如果卷号错了,就调整一下再重启
5、只是一个临时方案,不太适合移动设备,有些太麻烦了

Prolog101(09)

现在我们使用列表,重写一下room.pl文件。

%swipl -s roomlist.pl
%Hansen

%动态函数声明
:-dynamic here/1.
:-dynamic location_list/2.
:-dynamic bag_list/1.
:-dynamic take_thing/2.
:-dynamic put_thing/2.

%房间定义
room(X):- room_list(List),member(X,List).
room_list([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):- location_list(List, Y), member(X, List).
location_list([apple, broccoli, crackers], kitchen). 
location_list([desk, computer], office).
location_list([flashlight, envelope], desk).
location_list([stamp, key], envelope).
location_list([], hall).
location_list([], diningroom).
location_list([washingmachine], cellar). 
location_list([nani], washingmachine).

%房间减少物品
take_thing(Thing, Place):- 
retract(location_list(List, Place)),
delete(List,Thing,ThingsLeft),
asserta(location_list(ThingsLeft,Place)). 

%房间增加物品
put_thing(Thing, Place):-  
retract(location_list(List, Place)),
asserta(location_list([Thing|List],Place)).

%背包有哪些物品
bag(X):-bag_list(List), member(X, List).
bag_list([tourch]).

%背包增加物品
bag_in(Thing):- 
retract(bag_list(List)),
asserta(bag_list([Thing|List])).

%背包减少物品
bag_out(Thing):-
retract(bag_list(List)),
delete(List,Thing,ThingsLeft),
asserta(bag_list(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').

进行查询

%查找与kitchen相连的房间
1 ?- findall(X, connect(kitchen, X), List).
List = [office, cellar, diningroom].

%查找全部食物与位置
2 ?- findall(foodat(X,Y), (location(X,Y) , edible(X)), L).
L = [foodat(broccoli, kitchen), foodat(crackers, kitchen)].

swipl的奇怪报错

在windows下用swipl命令运行prolog脚本时,经常会遇到下面的错误:

ERROR: char_code/2: Cannot represent due to `character_code'

解决方法有两种:
1、使用swipl-win命令替代swipl命令
2、在macos下使用swipl命令

应该是一个bug,在读入字符时(如;),处理不当导致的。

MacOS使用Prolog命令行工具

1、看一下SWI-Prolog的安装说明,发现命令行工具在下面的路径

/Applications/SWI-Prolog.app/Contents/MacOS

2、修改PATH变量,添加SWI-Prolog命令行工具在下面的路径

#查看命令行工具
cd /Applications/SWI-Prolog.app/Contents/MacOS
ls

#查看PATH变量
echo "$PATH"

#修改PATH变量
vi $HOME/.bash_profile
#增加一行
export PATH=${PATH}:/Applications/SWI-Prolog.app/Contents/MacOS

3、重启命令行

#查看PATH变量
echo "$PATH"

#测试一下
swipl hello.pl 

MongoDB数据引用(Shell)

1、被引用数据

db.address.insert({"city":"shanghai","street":"huaihai road","no":"101"})
db.address.insert({"city":"beijing","street":"taipingqiao road","no":"102"})

2、引用数据

db.persons.insert({"name":"joe","address":{"$ref":"address","$id": ObjectId("55f522e96811e30fd403e83d"),"$db": "test"},"age":20,"sex":"male"})
db.persons.insert({"name":"leo","address":{"$ref":"address","$id": ObjectId("55f522f46811e30fd403e83e"),"$db": "test"},"age":21,"sex":"male"})

3、查询被引用数据

var user = db.persons.findOne({"name":"joe"})
var addressRef = user.address
db[addressRef.$ref].findOne({"_id":(addressRef.$id)})