有时候语句会看上去很是地奇怪,可是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的函子,用于构建非空列表,语句 []和 . 被称为列表构造器。
以下是这些列表构造器如何构建列表的。无需多说,这个定义确定是递归的:
经过下面的例子确保彻底理解这个定义:
?- .(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