Learn Prolog Now 翻譯 - 第九章 - 語句深究 - 第二節, 特殊表示法的語句

內容提要

  • 算術相關的語句
  • 列表語句

有時候語句會看上去很是地奇怪,可是Prolog內部可以正確地進行處理。好比,當咱們比較 a 和 'a'時,做爲人咱們看到了兩個不一樣的字符符號,可是Prolog會認爲它們是同一個東西。並且事實上,Prolog還會認爲其餘不少狀況下,兩個字符串是相同的語句。爲何?由於這使得編程更加容易。有時候對Prolog有用的表示法,對於開發者來講不是那麼友好。因此,若是可以讓開發者在編程時使用對人來講較爲友好的表示法,而後也讓Prolog瞭解其內部優化的表示法,就是很好的事情。編程


算術相關的語句

以前介紹過的一些算術謂詞就是很好的例子。正如咱們在第五章說起的,+,-,*,/都是函子,算術表達式好比,2+3,都是語句。這不是一個類比,除了藉助is/2謂詞的幫助,算術表達式可以進行計算的事實,Prolog會把字符串(好比 2+3)看作是普通的複雜語句,下面的查詢會讓這個過程更加清晰:優化

? 2 + 3 == +(2, 3).
true

? +(2, 3) == 2 + 3.
true

?- 2 - 3 == -(2, 3).
true

?- *(2, 3) == 2 * 3.
true

?- 2 * (7 + 2) == * (2, +(7, 2)).
true

簡而言之,熟悉的算術中綴表達法是爲了符合咱們的使用習慣,Prolog不會認爲這些和普通的語句有什麼不一樣。3d

相似地可使用的算術語句包括比較相關的謂詞:<, =<, =:=, ==, >, >= :code

?- (2 < 3) == <(2, 3).
true

?- (2 =< 3) == =<(2, 3).
true

?- (2 =:= 3) == =:=(2, 3).
true

?- (2 =\= 3) == =\=(2, 3).
true

?- (2 > 3) == >(2, 3).
true

?- (2 >= 3) == >=(2, 3).
true

這些例子展現了爲何有符合咱們習慣的算術表達式的好處(你情願不得不使用相似:=:=(2,3)的表達式麼?)。注意,咱們在語句等式判斷的左右兩邊加上了括號,好比,不會這樣查詢:blog

?- 2 =:= 3 == =:=(2,3).

而是這樣查詢:遞歸

?- (2 =:= 3) == =:=(2, 3).

爲何?由於Prolog會發現查詢,2 =:= 3 == =:=(2,3)有二義性。由於不能判斷這個表達式是:(2 =:= 3) == =:=(2, 3),仍是: 2 =:= (3 == =:=(2,3)),因此咱們必須使用小括號明確含義。開發

最後,咱們已經介紹了一些看上去很相像的符號,好比=, ==,和 =:=(還有=, ==, ==),以下是總結:字符串

= 合一謂詞。當參數可以合一時成功,不然失敗。原理

= 反合一謂詞。當=失敗時成功,=成功時失敗。語法

== 判等謂詞。若是參數相等時成功,不然失敗。

== 反判等謂詞。==失敗時成功,==成功時失敗。

=:= 算術相等謂詞,當參數爲相等的整數時成功,不然失敗。

== 反算術相等謂詞,當=:=失敗時成功,=:=成功時失敗。


列表語句

列表是Prolog中另一個有內部表示法的例子。Prolog爲使用者提供了很友好的外部表示方法(即,中括號表示法[]),事實上,由於Prolog同時還提供了「|」構建符號,因此存在不少效果相同的不一樣外部表示方法,以下:

?- [a, b, c, d] == [a | [b, c, d]].
true

?- [a, b, c, d] == [a, b | [c, d]].
true

?- [a, b, c, d] == [a, b, c | [d]].
true

?- [a, b, c, d] == [a, b, c, d | []].
true

可是Prolog內部若是表示列表的?事實上,它會把列表看做由兩個特殊的語句構成,其一是:[],表明空列表,其二是:"."(英文字符句號),一個元數爲2的函子,用於構建非空列表,語句 []和 . 被稱爲列表構造器。

以下是這些列表構造器如何構建列表的。無需多說,這個定義確定是遞歸的:

  • 空列表是[],它的長度爲0.
  • 非空列表是由形式爲:.( term, list)構成的語句,其中term是任意Prolog的語句,list是任意列表,若是list的長度是n,那麼.( term, list)的長度爲 n+1。

經過下面的例子確保徹底理解這個定義:

?- .(a, []) == [a].
true

?- .(f(d,e), []) == [f(d,e)].
true

?- .(a, .(b, [])) == [a, b].
true

?- .(a, .(b, .(f(d,e), []))) == [a, b, f(d,e)].
true

?- .(.(a,[]), []) == [[a]].
true

?- .(.(.(a, []), []), []) = [[[a]]].
true

?- .(.(a, .(b, [])), []) == [[a, b]].
true

?- .(.(a, .(b, [])), .(c, [])) == [[a, b], c].
true

?- .(.(a, []), .(b, .(c, []))) == [[a], b, c].
true

?- .(.(a, []), .(.(b, .(c, [])), [])) == [[a], b, c].
true

Prolog的列表內部表示法沒有外部中括號表示法那麼友好,不過也不是像第一眼看上去的那麼糟。事實上,它工做原理和「|」語法相似,它將列表表示爲兩個部分:列表的第一個元素(頭部),和列表的剩餘部分組成的列表(尾部)。內部表示法很像一棵樹。樹的內部節點,若是被標記了「.」,都有兩個子節點。在左端的子節點表明列表的頭元素,在右端的子節點表明剩餘的列表。好比,.(a, .(.(b, .(c, [])), .(d, []))),即[a, [b, c], d]的內部樹看上去像下圖的樣子:

最後說起一下,Prolog很是的友好,不單單侷限於咱們可以使用習慣的表示法查詢,它回答問題也使用便於咱們閱讀的方式:

?- .(f(d,e), []) = Y.
Y = [f(d,e)]
true

?- .(a, .(b, [])) X, Z = .(.(c,[]),[]), W = [1, 2, X].
X = [a, b]
Z = [[c]]
W = [1, 2, [a, b]]
true
相關文章
相關標籤/搜索