子程序体
按照子程序是否与主程序采用相同的语言来编写,而将子程序分为两种基本类型。最通用的子程序都是以同样语言编写的。这种子程序体通常具有与主程序相同的形式,不同的只是具有一个专门的初始语句。能够用这个语言编制程序的任何算法均可以置入子程序体中。其中所要求的算法可用语言所提供的初等运算、数据结构和控制结构来表达,这就提供了很灵活的扩充能力。在子程序和调用程序之问信息交换的限制通常是有的。
在算法不能按语吉定义的初等运算编码的地方,有效的是第二种类型的子程序,以另一种语言来编码的子程序。这种类型的子程序是不常见的,由于在不同的语言编写程序间存在相互通讯的困难,以及由于在存贮管理要求方面的差别,这类子程序的使用只限子相当特殊的情况。通常仅仅是预编译的FORTRAN或具有静态存贮要求的汇编语言子程序可以使用。1
子程序的运算项和结果如果子程序给出的是明显的结果,则该子程序属于函数子程序类(或称函数),如果完全是通过副作用工作而不给出明显结果,则称之为子例程(Subroutines)。函数子程序用于表达式计算。其计算结果作为其它运算的直接输入。子例程必须用专门的CALL语句单独调用。
子程序的运算项称之为实在参数或变元。子程序的运算项往往是比较自由的。一般地说,运算项可以是任何数据项,或是数,或是其它的初等数据项,或是像数组,表这样的数据结构。此外,其它子程序的名字常常也可作为运算项,有的也可以是语句标号。
子程序的结果似乎受到更多的限制,通过参数或非局部量的修改子程序的结果可以作为明显的函数值出现,也可通过副作用出现。在许多语言中,对子程序结果的限制是为了不影晌存贮管理。倒如,在FORTRAN和ALGOL语言中,普通的限制是子程序结果所需要的存贮必须在子程序开始执行之前进行分配,ALGOL中子程序可以以单个的数作为结果,也可以用任意的方法修改现存数据结构(并不改变结构的大小)的内容,但不可以自身产生和给出数据结构作为子程序的值。因此ALGOL子程序不能设置表和给出表作为它的值。代替的办法是在进入子程序之前先建立表。然后子程序可以填充该表(利用副作用)和返回控制。此外,子程序通常也不允许释放其运算项的存贮单元,这些限制的作用是为了只允许将子程序当作初等运算,生成、废弃或涉及到存贮管理的一些其它运算都是不可程序设计的。
在LIsP、SNOBOL4和APL语言中,使用了更为一般的存贮管理方法,子程序可以允许产生并给出数据结构的值。在这些语言中,当程序用于不同目的执行时,存贮分配大概是经常地进行的,而子程序的入口和出口的界限对于存贮管理程序并不是特别的关键。1
说明和子程序正如初等运算一样,在具有说明数据类型的语言中,有函数子程序结果类型说明是很重要的,类型说明构成了子程序定义的一部分。如在ALGOL中,子程序的标题:
integer procedure SUB(…);
按此说明,即可以确定在表达式:
X×SUB(…)+Y;
中SUB的调用将有整型结果,这就许可作静态的类型检查并将表达式翻译为特定类型的乘法和加法运算。1