1. 程式人生 > >Prolog教程 3

Prolog教程 3

facts, predicate,
pred(arg1,arg2,…argN).
argument type: interger, atom( low case begin, ’ '), variable(uppoer case begin or _), structure,
事實 (facts)
注:斜粗體字表示Prolog的專有名詞

事實(facts)是prolog中最簡單的謂詞(predicate)。它和關係資料庫中的記錄十分相似。在下一章中我們會把事實作為資料庫來搜尋。

謂詞: Prolog語言的基本組成元素,可以是一段程式、一個數據型別或者是一種關係。它由謂詞名和引數組成。兩個名稱相同而引數的數目不同的謂詞是不同的謂詞。

事實的語法結構如下:

pred(arg1, arg2, … argN).

其中pred為謂詞的名稱。arg1,…為引數,共有N個。‘.’是所有的Prolog子句的結束符。沒有引數的謂詞形式如下:

pred.

引數可以是以下四種之一:

整數(integer)
絕對值小於某一個數的正數或負數。

原子(atom)
由小寫字母開頭的字串。

變數(variable)
由大寫字母或下劃線(_)開頭。

結構(structure)
在以後的章節介紹。

不同的Prolog還增加了一些其他的資料型別,例如浮點數和字串等。

Prolog字符集包括: 大寫字母,A-Z;小寫字母,a-z;數字,0-9;±//^,.~:.?#$等。

原子通常是字母和數字組成,開頭的字元必須是小寫字母。例如:

hello
twoWordsTogether
x14

為了方便閱讀,可以使用下劃線把單詞分開。例如:

a_long_atom_name
z_23

下面的是不合法的原子,

no-embedded-hyphens
123nodigitsatbeginning
Nocapsfirst
下劃線不能放在最前面

使用單引號擴起來的字符集都是合法的原子。例如:

‘this-hyphen-is-ok’
‘UpperCase’
‘embedded blanks’

下面的由符號組成的也是合法的原子:

,++

變數和原子相似, 但是開頭字元四大寫字母或是下劃線。例如:

X
Input_List
下劃線開頭的都是變數
Z56

有了這些基本的知識,我們就可以開始編寫事實了。事實通常用來儲存程式所需的資料。例如,某次商業買賣中的顧客資料。customer/3。(/3表示customer有三個引數)

customer(‘John Jones’, boston, good_credit).
customer(‘Sally Smith’, chicago, good_credit).

必須使用單引號把顧客名引起來,因為它們是由大寫字母開頭的,並且中間有空格。

再看一個例子,視窗系統使用事實儲存不同的視窗資訊。在這個例子中引數有視窗名稱和視窗的位置座標。

window(main, 2, 2, 20, 72).
window(errors, 15, 40, 20, 78).

某個醫療專家系統可能有如下的疾病資料庫。

disease(plague, infectious). {疾病(瘟疫,有傳染性)}

Prolog的直譯器提供了動態儲存事實和規則的方法,並且也提供了訪問它們的方法。資料庫的更新是通過執行‘consult’或‘reconsult’命令。我們也可以直接在直譯器中輸入謂詞,但是這些謂詞不會被儲存到硬碟上。

尋找Nani

下面我們正式開始“尋找Nani”遊戲的編寫。我們從定義基本的事實開始,這些事實是本遊戲的基本的資料庫。它們包括:

房間和它們的聯絡
物體和它們的位置
物體的屬性
玩家在遊戲開始時的位置

“尋找Nani”遊戲的的房間格局

首先我們使用room/1謂詞定義房間,一共有五條子句,它們都是事實,如圖2.1。

room(kitchen).
room(office).
room(hall).
room(‘dining room’).
room(cellar).

我們使用具有兩個引數的謂詞來定義物體的位置。第一個引數代表物體的名稱,第二個引數表示物體的位置。開始時,我們加入如下的物體。

location(desk, office).
location(apple, kitchen).
location(flashlight, desk).
location(‘washing machine’, cellar).
location(nani, ‘washing machine’).
location(broccoli, kitchen).
location(crackers, kitchen).
location(computer, office).

注意:我們定義的那些符號,例如:kitchen、desk等對於我們是有意義的,可是它們對於Prolog是沒有任何意義的,完全可以使用任何符號來表示房間的名稱。

謂詞location/2的意思是“第一個引數所代表的物體位於第二個引數所代表的物體中”。Prolog能夠區別location(sink, kitchen)和location(kitchen, sink)。因此,引數的順序是我們定義事實時需要考慮的一個重要問題。

下面我們來表達房間的聯絡。使用door/2來表示兩個房間有門相連,這裡遇到了一個小小的困難:

door(office, hall).

我們想要表達的意思是,office和hall之間有一個門。可是由於Prolog能夠區分door(office, hall)和door(hall, office), 所以如果我們想要表達一種雙向的聯絡,就必須把每種聯絡都定義一遍。

door(office, hall).
door(hall, office).

引數的順序對定義物體的位置有幫助,可是在定義房間的聯絡時卻帶來了麻煩。我們不得不把每個房門都定義兩次!

在這一章裡,只定義單向的門,以後會很好地解決此問題的。

door(office, hall).
door(kitchen, office).
door(hall, ‘dining room’).
door(kitchen, cellar).
door(‘dining room’, kitchen).

下面定義某些物體的屬性,

edible(apple).
edible(crackers).

tastes_yucky(broccoli).

最後,定義手電筒(由於是晚上,玩家必須想找到手電筒,並開啟它才能到那些關了燈的房間)的狀態和玩家的初始位置。

turned_off(flashlight).
here(kitchen).