pred(x):- pred(y),pred(z).
前面我們已經說過,謂詞是使用一系列的子句來定義的。以前我們所學習的子句是事實,現在讓我們來看看規則吧。規則的實質就是儲存起來的查詢。它的語法如下:
head :- body
其中,head 是謂詞的定義部分,與事實一樣,也包括謂詞名和謂詞的引數說明。
:- 連線符,一般可以讀作『如果』。
body 乙個或多個目標,與查詢相同。
舉個例子,上一章中的混合查詢–找到能吃的東西和它所在的房間,可以使用如下的規則儲存,規則名為where_food/2。
where_food(x,y) :- location(x,y), edible(x).
用語言來描述就是「在房間y中有可食物x的條件是:x在y房間中,並且x可食。」
我們現在可以直接使用此規則來找到房間中可食的物品。
?- where_food(thing, 『dining room』).
no它也可以用來判斷,
或者通過它找出所有的可食物及其位置,
thing = crackers
room = kitchen ;
no我們可以使用多個事實來定義乙個謂詞,同樣我們也可以用多個規則來定義乙個謂詞。例如,如果想讓prolog知道broccoli(椰菜)也是可食物,我們可以如下定義where_food/2規則。
where_food(x,y) :- location(x,y), edible(x).
where_food(x,y) :- location(x,y), tastes_yucky(x).
在以前的事實中我們沒有把broccoli定義為edible,即沒有edible(broccoli).這個事實,所以單靠where_food的第乙個子句是不能找出broccoli的,但是我們曾在事實中定義過:tastes_yucky(broccoli).,所以如果加入第二個子句,prolog就可以知道broccoli也是food(食物)了。下面是它的執行結果。
規則的工作原理
到現在為止,我們所知道的prolog所搜尋的子句只有事實。下面我們來看看prolog是如何搜尋規則的。
首先,prolog將把目標和規則的子句的頭部(head)進行匹配,如果匹配成功,prolog就把此規則的body部分作為新的目標進行搜尋。
實際上規則就是多層的詢問。第一層由原始的目標組成,從下一層開始就是由與第一層的目標相匹配的規則的body中的子目標組成。(這句話有點難理解,請參照下面圖來分析)
每一層還可以有子目標,理論上來講,這種目標的巢狀可以是無窮的。但是由於計算機的硬體限制,子目標只可能有有限次巢狀。
下圖顯示了這種目標巢狀的流程圖,請你注意第一層的第三個目標是如何把控制權回溯到第二層的子目標中的。
在這個例子中,第一層的中間的那個目標的結果依賴於第二層的目標的結果。此目標會把程式的控制權傳給他的子目標。
下面我們詳細地分析一下prolog在匹配有規則的子句時是如何工作的。請注意用『-』分隔的兩個數字,第乙個數字代表當前的目標級數,第二個數字代表當前目標層中正在匹配的目標的序號。例如:
2-1 exit (7) location(crackers, kitchen)
表示第二層的第乙個目標的exit過程。
在詢問的不同層的目標中,即是相同的變數名稱也是不同的變數,因為它們都是區域性變數。這於其他語言中的區域性變數是差不多的。
我們再來分析一下上面的那個例子吧。
where_food(x,y) :- location(x,y), edible(x).
查詢的目標是:
?- where_food(x1, kitchen)
第乙個子句的頭是:
where_food(x2, y2)
目標和子句的頭部匹配,在prolog中如果變數和原子匹配,那麼變數就繫結為此原子的值。如果兩個變數進行了匹配,那麼這兩個變數將同時繫結為乙個內部變數。此後,這兩個變數中只要有乙個繫結為了某個原子的值,另外乙個變數也會同時繫結為此值。所以上面的匹配操作將有如下的繫結。
x1 = _01 ;01為prolog的內部變數。
x2 = _01
y2 = kitchen
於是當上述的匹配操作完成後,規則where_food/2的body將變成如下的查詢:
location(_01, kitchen), edible(_01).
使用規則
使用規則我們可以很容易的解決單向門的問題。我們可以再定義有兩個子句的謂詞來描述這種雙向的聯絡。此謂詞為connect/2。
connect(x,y) :- door(x,y).
connect(x,y) :- door(y,x).
它代表的意思是「房間x和y相連的條件是:從x到y有扇門,或者從y到x有扇門"。請注意此處的或者, 為了描述這種或者的關係我們可以為某個謂詞定義多個子句。
?- connect(kitchen, office).
yes?- connect(office, kitchen).
yes我們還可以讓prolog列出所有相連的房間。
?- connect(x,y).
x = office
y = hall ;
x = kitchen
y = office ;
…x = hall
y = office ;
x = office
y = kitchen ;
…先定義list_things/1,它能夠列出某個房間中的物品。
list_things(place) :-
location(x, place),
tab(2),
write(x),
nl,fail.
它和上一章中的最後乙個例子差不多。我們可以如下使用它。
這地方有乙個小問題,它雖然把所有的東西都列出來了,但是最後那個no不太好看,並且如果我們把它和其他的規則連起來用時麻煩就更大了,因為此規則的最終結果都是fail。實際上它是我們擴充的i/o謂詞,所以它應該總是成功的。我們可以很容易的解決這個問題。
list_things(place) :-
location(x, place),
tab(2),
write(x),
nl, fail.
list_things(anyplace).
如上所示,加入list_things(anyplace)子句後就可以解決了,第乙個list_things/1的子句把所有的物品列出,並且失敗,而由於第二個子句永遠是成功的,所以list_things/1也將是成功的。anyplace變數的值我們並不關心,所以我們可以使用無名變數『_』來代替它。
list_things(_).
下面我們來編寫list_connections/1,它能夠列出與某個房間相連的所有房間。
list_connections(place)
:- connect(place, x),
tab(2),
write(x),
nl,fail.
list_connections(_).
我們來試試功能,
?- list_connections(hall).
dining
room
office
yes終於可以來編寫look/0了,
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).
在我們定義的事實中有here(kitchen).它代表玩家所在的位置。以後我們將學習如何改變此事實。現在來試是功能吧,
Prolog教程 4 簡單查詢
goal 查詢目標 unification 匹配工作三個必要哦條件1.目標謂詞一致 2.謂詞引數數量一致 3.所有引數相同 查詢繼續 查詢4個埠 1.call 開始查詢 2.exit 成功查詢到結果,並繫結到變數 3.redo 從上次成功查詢處之後繼續查絢,先釋放變數 4.fail 查詢失敗退出 現...
Prolog教程 5 組合查詢
常用內部謂詞 write 1 此謂詞被呼叫時永遠是成功的,並且它可以把它的引數作為字串輸出到螢幕上。當回溯時,它永遠是失敗,所以回溯是不會把已經寫到螢幕上的字元又給刪除的。nl 0 此謂詞沒有引數,和write一樣,從call埠呼叫時總是成功的,從redo埠回溯時總是失敗的,它的作用是在螢幕上輸出乙...
Prolog中文教程 簡單的查詢
現在我們的遊戲中已經有了一些事實,使用prolog的直譯器調入此程式後,我們就可以對這些事實進行查詢了。本章和下一章中的prolog程式只包括事實,我們要學會如何對這些事實進行查詢。prolog的查詢工作是靠模式匹配完成的。查詢的模板叫做目標 goal 如果有某個事實與目標匹配,那麼查詢就成功了,p...