内容摘要:
原子(Atom)
数字(Numbers)
变量(Variables)
复杂语句(Complex Terms)
通过上一节的学习,我们已经大概熟悉了Prolog的编程思路,这一节我们会回过头,详细学习其中的一些语法细节。首先,问一个基础的问题:我们已经在Prolog程序中看到了很多类型的表达式
(比如,jody,playsAirGuitar(mia),和X),但这些仅仅只是例子,是时候更加深入了,到底事实、规则和查询是由什么构成的?
答案就是语句(terms),在Prolog中一共存在四种类型的语句:原子,数字,变量和复杂语句(或者称为结构)。原子和数字统称为常量,常量和变量统称简单语句。
首先要明确基础的字符的范围:大写字母:A,B,...,Z;小写字母:a,b,...,z;数字:0,1,2,...,9.另外还包括"_",即英文下划线字符;和其他一些特殊英文字符,比如:+,-,*,/,<,>,=,:,.,
&,~;空格也是字符,但是不常用,并且也不可见。字符串是指没有切断的字符序列。
原子(Atoms)
一个原子是以下情况之一:
1. 由字符构成的字符串,其中有效字符包括:大字字母,小写字母,数字,和下划线,并且是小写字母作为头字符。一些例子:butch,big_kahuna_burger,listen2Music,playsAirGuitar。
2. 使用单引号封装的字符序列。比如:‘Vincent‘,‘The Gimp‘,‘Five_Dollar_Shake‘,‘&^%%@# *‘,‘ ‘。被单引号封装的字符序列被称为原子名。注意我们已经使用了空格字符,事实上,
使用单引号封装,其中的一个作用就是可以在原子钟精确地使用类似空格字符这样的特殊字符。
3. 特殊字符组成的字符串。比如:@=,====>,;,:-等都是原子。正如我们看到的,一些特殊原子,比如;(逻辑或),:-(规则中连接头部和主干的符号)已经有预定义的含义。
数字(Numbers)
在典型的Prolog程序中,实数并不是很有用武之地。所以虽然大多数Prolog的实现都支持浮点数,但是本文不讨论。
但是整数(比如:-2,-1,0,1,2,...)却十分有用,比如在计算列表的元素数目之类的工作时候,我们将会在第5章详细介绍。Prolog中数字的表示很简单,没有什么特殊,如下:
23, 1001, 0, -365, 等等。
变量(Variables)
变量是由大写字母,小写字母,数字和下划线组成的字符串,并且头字母必须是大写字母或者下划线。比如:
X, Y, Variable, _tag, X_526, List, List24, _head, Tail, _input, Output
都是Prolog中有效的变量。变量”_“是一个特例,它被称为匿名变量,我们将会在第4章中介绍。
复杂语句(Complex Terms)
常量,数字,和变量都是构建模块,现在我们学习如何将它们组成复杂语句。复杂语句也并称为结构体。
复杂语句由一个函子(functor,也可以理解为函数名)和一个参数序列构成。参数序列放在小括号内,由英文逗号分隔,并且是放在函子后面。请注意函子后面必须紧跟参数序列,中间不能
有空格。函子必须是一个原子,即,变量不能用作函子。另一方面,参数序列可以是任何类型的语句。
从KB1到KB5,我们已经看到了许多复杂语句的例子。比如,playsAirGuitar(jody)就是一个复杂语句,其中playsAirGuitar是函子,jody是参数序列(只有一个参数)。另一个例子是
loves(vincent, mia),loves是函子,vincent和mia是参数序列;再比如一个包含了变量的例子:jealous(marsellus, W)。
但是,复杂语句的定义可以允许更为复杂的情况。事实上,在复杂语句中,也可以内嵌其他复杂语句(就是说,复杂语句允许递归)。比如:
hide(X, father(father(father(butch)))).
就是一个完美的符合定义的复杂语句。它的函子是hide,有两个参数:一个是变量X,另外一个是复杂语句,father(father(father(butch)))。这个复杂语句组成是:函子是father,另外一
个复杂语句,father(father(butch))是其唯一的参数。里层的复杂语句的参数依然是一个复杂语句:father(butch)。但是到了嵌套的最里层,参数就是一个常量:butch。
实际上,这种嵌套(递归结构)使得我们可以自然地描述很多问题,而且这种递归结构和变量合一之间的互相作用,正是Prolog强有力的武器。
复杂语句的参数个数称为元数(arity)。比如,woman(mia)是一个元数为1的复杂语句,loves(vincent, mia)是一个元数为2的复杂语句。
元数对于Prolog很重要。Prolog允许定义函子相同但是元数不同的复杂语句。比如,我们可以定义两个参数的loves谓词,loves(vincent, mia);也可以定义三个参数的loves谓词,loves(
vincent, marsellus, mia)。如果我们这么做了,Prolog会认为这两个谓词是不同的。在第5章中,我们将会看到定义相同函子但是元数不同的具体应用。
当我们需要提及定义的谓词,介绍如何使用它们的时候(比如,在文档中),惯例是”函子/元数“这种形式。回到KB2,我们有三个谓词,之前的表达如下:
listen2Music
happy
playsAirGuitar
使用正式的书写方式如下:
listen2Music/1
happy/1
playsAirGuitar/1
Prolog不会因为定义了两个loves谓词而迷惑,它会区分loves/2和loves/3是不同的谓词。