非过程语言是一种计算机程序设计语言,是相对于过程语言而言的,其语言的组织不是围绕于过程的。它同过程语言的区别是非过程语言编写的程序可以不必遵循计算机执行的实际步骤,使人们无须关心问题的解法和计算过程的描述。在非过程语言中,只要指明输入记录、所要完成的加工以及输出形式,便能得到所要求的输出结果,其余工作全部由系统来完成。其主要优点是可减少程序员编程的工作量。
当前使用的非过程语言种类很多:一类是以LISP,FP等为代表的函数式程序设计语言;一类是以PROLOG为代表的逻辑型程序设计语言;还有一类称为面向对象的程序设计语言,其典型语言是Smalltalk。
在编写非过程语言程序时一般要遵守下列步骤:
1.执行内务处理,例如清存储器、预置计数器初值等;
2.打开文卷,检查标号;
3.读输入记录;
4.执行算术或逻辑运算;
5.产生输出记录;
6.重复步骤3—5,直到处理完全部记录;
7.打印最终的输出记录,关闭文卷;
8.结束程序或将控制返回操作系统.
非过程这一术语是相对的,它随技术水平的变化而变化。无论如何,较少过程的这一用语较佳,因为它明确了这一概念的相对性。考察图1将使这个问题更清楚。比较图1 (a)和1(a*),表明了汇编语言与类Fortran语言之间的差别。在Fortran存在之前,表达式A=(B+C) *D+E*F可认为是非过程的,因为它不能被任何语言加工程序所直接翻译。同样,图1(b)与1(b*)示出另一级的相对性,因为进行矩阵相乘的Fortran程序在APL中可用一个语句来处置。在Fortran中采用子例程序并不给出附加的非过程性,因为过程性乃基于语言的基元。最后,图1(c*)示出一个程序,它计算素数3到95的平方根并按两列打印(CALCULATE THE SQUARE ROOT OF THE PRIME NUMBERS FROM 3 TO 95 AND PRINT IN TWO COLUMNS),它不能被任何至今已知的翻译系统所处置,但是如果它能的话,按1980标准,该语言可认为是非过程的。一个系统“理解”英语的能力不在这里争论;看起来象英语的短语实际上取决于特定的程序设计技术(例如模式匹配与宏扩展),而不是英语的文法。用另一方式陈述这一观点(由于其在这事情至为重要),完全可能设计一个形式语言来做数学问题,其中可接受CALCULATE THE SQUARE ROOT OF THE PRIME NUMBERS FROM 3 TO 95 AND PRINT IN TWO COLUMNS这一语句。在另一极端,象FIND x SUCH THAT X**2=5(求x使x2=5) 这样的看起来自然又优雅的短语实际上等效于调用一个平方根例行程序。因此,非过程性与英语表示法是完全无关的两个方面。
图1
(a) (a*)
(assembly Language) (Fortran)
CLA B A=(B+C)*D+E*F
ADD C MPY D STO T CLA E MPY F ADD T STO A
(b) (b*)
(Fortran) (APL)
DO 71=1,M A←B+.×C DO 8J=1,N C(1,J)=0
DO 9K=1,L C(1,J)=C(1,J)+A(1,K)*B(K,J)
9 CONTINUE
8 CONTINUE
7 CONTINUE
(c)
(PL/1) (c*)
DO 1=3 TO 95 BY 2; PRINT(2)
IF PRIME(1) SQ(PRIME(3,95))
THEN PUT SKIP LIST
(1,SQRT(1)); 或
ELSE RETURN;
END; CALCULATE THE SQUARE
ROOT OF THE PRIME
NUMBERS FROM 3 TO
95 AND PRINT IN
2 COLUMNS
在很早期的程序设计 (即50年代的前5年)中,自动程序设计这个词用来表示用某一高级语言来编写一个程序的过程。其中“高级”是与机器代码相比较。随着时间推移,显然编码只是整个解题任务的一部分,所以用自动编码这个词来表示采用诸如Fortran这样的语言。因此,甚至在很早期,在编码(它是整个程序设计任务中的一个方面)和说明与设计这一大量活动之间作出了适当的区别。第一批重要的成就之一是在Information Algebra的开发中Codasyl Languange Structure Group的工作。这实质上是利用输入/输出关系来描述数据处理应用的一种面向数学的方法;这些输入/输出关系实际上是利用对称为区域(类似于文件)的实体集合的变换来定义的。作为另一个例子,我们注意到,象 Comit与Snobol这样的面向字符串与模式的语言对于那些特征的过程性比Fortran与Cobol这样的语言少得多。
Lisp 语言最早是在 20 世纪 50 年代末由麻省理工学院(MIT)为研究人工智能而开发的。Lisp 语言的强大使它在其它方面诸如编写命令和集成环境等显示其优势。而 GNU Emacs Lisp 主要由 Maclisp 发展而来。它在某种程度上继承了 Common Lisp,而 Common Lisp 在 20 世纪 80 年代成了一种标准。 Lisp 代表 LISt Processing,即表处理,这种编程语言用来处理由括号(即“(”和“)”)构成的列表。
相联引用
我们将使用相联引用这个术语来指基于数据的本征性质的数据存取。相联引用通常在那些把集合作为数据结构的语言中提供。从原先定义的集合中选择元素和基于成员的某一特性从老的集合中定义新的集合,这样的操作有时称为集合形成(例如,见SETL——q. v.)。SETL的功能的一个例子可由下列表达式看到,它说明在2与100之间的素数。
{P,2<=P<=100↑
( 2<=N<P↑(P//N)NE、O)}
用英语这可读为“the set of P’s between 2 and 100 such that for every N greater than or equal to 2 and less than P,the remainder of P/N is not equal to zero”(在2与100 之间的P的集合,使每个大于或等于2且小于P的 N,P/N的余数不等于零)。(这个说明显然不是高效的;实用的算法至少是只应考虑从3到100的奇数。)
在非过程语言中相联引用的重要性在于程序员不必显式说明存取路径或把一算法编成程序以便指导对一特定数据结构的查找。相联引用也用于数据库管理语言中。
Codd(1972)定义了对关系的代数操作,这些代数作给出语言与这一类型的数据结构的相对能力的量度。除了笛卡儿乘积、逻辑或、逻辑与等传统的集合操作之外,他定义了投影、连接、相除与限定等相关操作。这些操作符(见下面的聚集操作符)有效地提供各种类型的相联引用。
聚集操作符
在提供聚集操作符的一些程序设计语言中可避免编写循环。APL中的十操作符可同等地用于标量与聚集,就是这类操作符的一个最简单的例子。例如,两个向量X、Y的相加只要写X+ Y就可获得,而在其他大多数程序设计语言中,结果向量的各元素必须在循环的控制下一次一个地获得。在APL中的聚集操作符的另一个例子是使用归约操作符来求一个向量X的各元素之和,如下列表达式所示:+/X。在有些情况下,PL/I程序员可通过采用对整个数组或结构都分布的若干操作符(例如赋值与相加操作符,如A=B+C,其中A、B、与C是数组)的方法来避免循环。
在相联引用与我们正在讨论的聚集操作符之间有密切的关系。显然,Codd(1972)对关系定义的代数操作符是聚集操作符。无疑,采用这个手段来消除显式的定序是一个非过程的特征。
在数据处理应用(但只用于说明)很有用的两个聚集操作符是在Information Algebra(Codasyl,1962) 中提出的BUNDLE与GLUMP这两个操作符。 GLUMP操作符把一个区域(它如同一个文件)划分成称为元素的子集,使一个元素含有在该区域中具有对给定的GLUMP操作符相同值的所有实体。 GLUMP操作符用于分组与归纳,这些是数据处理中的典型任务。例如,给定一组顾客订货单,其中可能有的顾客有一个以上的订货单,GLUMP操作可用 GLUMP(CUST#,ORDERS)表示。这个操作的结果是对ORDERS进行划分,使一个分区中的各订货单有相同的订货单号。BUNDLE操作符对有序的区域集合进行工作,对于笛卡儿乘积的每个成员,只选择满足某一条件(例如在一特定域中值的相等)的那些实体。
任意定序的消除
我们把任意定序定义为不是用应用的数据相关性所指挥的任何定序。
函数型程序设计语言是或不包含赋值语句或不包括GOTO语句的语言。因此,“函数型”看来是“非过程”的同义词,因为它更多地包含对输入函数所要求的输出的规定,而不是指出程序步骤的逐步序列。用诸如纯Lisp这样的函数型语言编写的程序可避免一些副作用,这些副作用是过程程序设计的伴随物。在过程语言中的一个副作用是在表达式计算期间因一个赋值语句而修改存储(例如在表达式中一个函数的计算期间)造成的。纯函数型语言不产生副作用,因为它们没有赋值操作,它们不能在表达式计算期间修改存储。
函数型程序设计的一个例子是APL“单线”操作(没有赋值或没有带副作用的函
数调用)。在下列 APL单线函数中将从向量X删除先行元素,其中 QTEMP表示一个加引号的字符串或含有要删除的示样的数字向量。缺少任意定序的最终表达式是纯数据流程序设计语言。在这种形式方法中,应用被分解成一组模块,一个模块在它被另一模块产生之后可只消耗(即 RESULT得到其输入数据)一特定值,和反之。定序是由数据相关性严格控制的。著名的数据流程序设计语言的最佳例子是GPSS(通用系统模拟语言),在其中一个模拟程序的定序是由传过该模型的事务(数据)所控制的。
RPG与非过程语言的关系
在讨论非过程语言时往往提到RPG(报表程序的生成程序)。无疑,一个RPG的输出格式是通过说明要什么而不是它应如何产生的方法指定的。但是,应该指出,一个 RPG程序的Calculation(计算)部分明确地是属于低层。这证实了我们关于没有一种语言在绝对意义上是非过程的这一说法。一个具体语言可具有某些特征而缺乏其他特征,或者在一个方面具有某一特征而在另一个方面缺乏此同一特征。