跳转到内容

ALGOL 68

维基百科,自由的百科全书
ALGOL 68
编程范型多范型指令式过程式结构化并发
设计者阿德里安·范·韦恩加登, B.J. Mailloux英语Barry J. Mailloux, J.E.L. Peck英语John E. L. Peck, C.H.A. Koster英语Cornelis H.A. Koster等人
发行时间最终报告: 1968年,​56年前​(1968
型态系统静态强类型安全结构式英语Structural type system
网站Revised Report on the Algorithmic Language ALGOL 68
主要实作产品
ALGOL 68C英语ALGOL 68C, ALGOL 68 Genie(新近[1]), ALGOL 68-R英语ALGOL 68-R, ALGOL 68RS英语ALGOL 68RS, ALGOL 68S英语ALGOL 68S, FLACC英语FLACC, 列宁格勒ALGOL 68, Odra英语Odra (computer) ALGOL 68
衍生副语言
ALGOL 68r0 (最终报告:1968年),
ALGOL 68r1 (修订报告:1973年)
启发语言
ALGOL 60, ALGOL Y英语ALGOL Y
影响语言
C[2]C++[3]Bourne shellKornShellBashSteelman英语Steelman language requirementsAdaPython[4]Seed7英语Seed7Mary英语Mary (programming language)S3英语S3 (programming language)

ALGOL 68(源自英语:ALGOrithmic Language 1968的缩写),一种指令式编程语言,为ALGOL家族的成员,是官方上的ALGOL 60后继者。它设计的目标,是提供更广泛的应用,以及更严格的语法定义。

ALGOL 68的特征包括基于表达式英语Expression-oriented programming language的语法,用户声明的类型结构/标记联合,变量和引用参数的引用模型,字符串、数组和矩阵的分片英语array slicing,以及并发

概论

ALGOL 68由IFIP工作组2.1英语IFIP Working Group 2.1负责设计。1968年12月20日,IFIP工作组2.1通过了这个语法规范,并提交IFIP大会通过且出版。

ALGOL 68的定义使用了阿德里安·范·韦恩加登发明的一种数学形式主义的两级形式文法Van Wijngaarden文法英语Van Wijngaarden grammar使用分别称为“超文法”和“元文法”的两组上下文无关文法规则,生成形成一个可能无限的产生式集合,而这些常规的产生式将识别特定的ALGOL 68程序;值得注意的是,它们能够表达在很多其他编程语言的技术标准中被标记为“语义”的那种要求,其他语言的语义必须用易致歧义的自然语言叙述来表达,并接着在编译器中实现为附加到形式语言解析器的“特设”代码。

ALGOL 68设计的主要目标和原则为:

  1. 描述的完备性和清晰性[5]
  2. 设计的正交性[6]
  3. 安全性[5]
  4. 高效性[5]

ALGOL 68曾受到批评,最突出的是来自其设计委员会的一些成员比如C. A. R. Hoare[7],还有ALGOL 60编译器作者比如Edsger Dijkstra[8],它抛弃了ALGOL 60的简单性,成为了复杂或过于笼统的想法的载体,不能使编译器作者的任务变得更轻易些,与刻意保持简单的同时代(竞争)者如CS-algol英语S-algolPascal形成了鲜明对比。

在1970年,ALGOL 68-R英语ALGOL 68-R成为了第一个投入工作的ALGOL 68编译器。

在1973年9月确定的修订版本中,省略了特定特征比如过程化、gomma和形式边界[5]

Stephen R. Bourne是ALGOL 68修订委员会成员,他选取了它的一些想法到他的Bourne shell之中。

ALGOL 68的语言定义出版后的文本长达两百多页并充斥着非标准术语,这种复杂性使得编译器实现变得困难,故而它曾被称为“没有实现也没有用户”。这么说只是部分真实的,ALGOL 68曾应用于一些小众市场,特别是流行于英国国际计算机有限公司英语International Computers Limited(ICL)的机器之上,还有在教学角色之上。在这些领域之外,其使用相对有限。

尽管如此,ALGOL 68对计算机科学领域的贡献是深刻、广泛而持久的,虽然这些贡献大多只是在它们于后来开发的编程语言中重现之时才被公开认可。很多语言是为了应对这门语言的复杂性而专门开发的,其中最著名的是Niklaus WirthALGOL WPascal[9],或者是针对特定角色而重新实现的,比如有些人认为Ada可以看作ALGOL 68的后继者[10]

1970年代的很多语言可以追溯其设计至ALGOL 68,选取一些特征,并放弃被认为太复杂或超出给定角色范围的其他特征。其中就有C语言,它受到ALGOL 68的直接影响,特别是它的强类型和结构。多数现代语言都至少可以追溯其部分语法至要么C语言要么Pascal,因而很多语言可直接或间接的经由C语言而追溯至ALGOL 68。

规定和实现时间线

名称 用途 国家 描述 目标CPU 属主/许可证 实现语言
广义ALGOL 1962 科学  荷兰 广义文法的ALGOL[11]
ALGOL 68DR 1968 草案 Does not appear IFIP WG 2.1草案报告[12] Does not appear
ALGOL 68r0 1968 标准 Does not appear IFIP WG 2.1最终报告[13] Does not appear
ALGOL 68-R英语ALGOL 68-R 1970 军用  英国 GEORGE 3英语GEORGE (operating system)之下的ALGOL 68 ICL 1900英语ICT 1900 series 皇家雷达研究所英语Royal Radar Establishment ALGOL 60
DTSS ALGOL 68 1970  美国 Dartmouth分时系统英语Dartmouth Time Sharing System的ALGOL 68[14] GE-635英语GE-600 series 达特茅斯学院
Mini ALGOL 68 1973 研究  荷兰 针对简单ALGOL 68程序的解释器[15] 可移植解释器 荷兰数学中心 ALGOL 60
OREGANO 1973 研究  美国 实践“实现模型的重要性。”[16] 加州大学洛杉矶分校
ALGOL 68C英语ALGOL 68C 1975 科学  英国 剑桥ALGOL 68 ICL英语International Computers LimitedIBM System/360PDP-10UnixTelefunken,Tesla和Z80(1980年)[17] 剑桥大学 ALGOL 68C
ALGOL 68r1 1975 标准 Does not appear IFIP WG 2.1修订报告[18] Does not appear
Algol H 1975 实验等  英国 对ALGOL 68的模态系统提议了扩展[19] ALGOL W
CDC ALGOL 68 1975 科学  美国 完全实现的ALGOL 68[20] CDC 6000系列英语CDC 6000 seriesCDC Cyber 控制数据公司
Odra英语Odra (computer) ALGOL 68 1976 实用  苏联/ 波兰 Odra 1204/IL ALGOL 60
俄克拉何马ALGOL 68 1976 编程指导  美国 俄克拉何马州立大学实现[21] IBM 1130System/370 Model 158英语IBM System/370 俄克拉何马州立大学 ANSI Fortran 66
柏林ALGOL 68 1977 研究  德国 柏林ALGOL 68实现[22] 抽象ALGOL 68机器 – 机器无关编译器 柏林工业大学 CDL 2英语Compiler Description Language
FLACC英语FLACC 1977 多用途  加拿大 具有调试特征的修订报告完整实现 System/370 租用,Chion公司 汇编
ALGOL 68RS英语ALGOL 68RS 1977 军用  英国 可移植编译器 ICL 2900系列英语ICL 2900 SeriesMulticsVMSC生成器(1993年) 皇家信号与雷达研究所英语Royal Signals and Radar Establishment ALGOL 68RS
ALGOL 68-RT英语ALGOL 68-RT 1979 科学  英国 并行ALGOL 68-R
ALGOL 68+ 1980 科学  荷兰 提议的ALGOL 68的超语言[23]
M-220英语M-220 ALGOL 68  苏联 M-220 EPSILON英语EPSILON (programming language)
列宁格勒ALGOL 68 1980 电信  苏联 完全语言 + 模块 IBM,DEC,CAMCOH,PS 1001和PC
交互式ALGOL 68英语Interactive ALGOL 68 1983  英国 增量编译 PC 非商业共享软件
ALGOL 68S英语ALGOL 68S 1985 科学  英国 ALGOL 68的子集语言[24] Sun-3英语Sun-3,Sun SPARC(在SunOS 4.1和Solaris 2下),Atari ST(在GEMDOS下),Acorn Archimedes英语Acorn Archimedes(在RISC OS下),VAX-11英语VAX-11(在Ultrix-32英语Ultrix下) 曼彻斯特维多利亚大学 BLISS英语BLISS
MK2 交互式ALGOL 68英语Interactive ALGOL 68 1992  英国 增量编译 PC 非商业共享软件[25]
A68toC[26] 1993 电子  英国 基于源自1985年ELLA英语ELLA (programming language) ALGOL 68RS英语ALGOL 68RS的ctrans 可移植C生成器 国防研究局英语Defence Research Agency皇冠版权开源软件 ALGOL 68RS
ALGOL 68 Genie 2001 完全语言  荷兰 包括标准的并立子句 可移植解释器 GNU GPL C
ALGOL 68 Genie版本2 2010 完全语言  荷兰 可移植解释器;可选的选定单元的编译 GNU GPL C

样例代码

下面的样例代码实现了埃拉托斯特尼筛法来找到小于等于100的所有素数。ALGOL 68中NIL类似于其他语言中的空指针x OF y表示访问STRUCT y的成员x

BEGIN # ALGOL68的素数筛法,基于链表实现 #
    MODE
        LIST = REF NODE,
        NODE = STRUCT (INT h, LIST t);
    OP  CONS = (INT n, LIST l) LIST: HEAP NODE := (n, LIST: l);
    PRIO CONS = 9;
    PROC one to = (INT n) LIST:
        (PROC f = (INT m) LIST: (m > n | NIL | m CONS f(m+1));
         f(1));
    PROC error = (STRING s) VOID:
        (print((newline, " error: ", s, newline)); GOTO stop);
    PROC hd = (LIST l) INT:
        (l IS NIL | error("hd NIL"); SKIP | h OF l);
    PROC tl = (LIST l) LIST:
        (l IS NIL | error("tl NIL"); SKIP | t OF l);
    PROC show = (LIST l) VOID:
        (l ISNT NIL | print((" ", whole(hd(l), 0))); show(tl(l)) 
         | print(newline));
    PROC filter = (PROC (INT) BOOL p, LIST l) LIST:
        IF l IS NIL THEN NIL
        ELIF p(hd(l)) THEN hd(l) CONS filter(p, tl(l))
        ELSE filter(p, tl(l))
        FI;
    PROC sieve = (LIST l) LIST:
        IF l IS NIL THEN NIL
        ELSE
            PROC not multiple = (INT n) BOOL: n MOD hd(l) NE 0;
            hd(l) CONS sieve(filter(not multiple, tl(l)))
        FI;
    PROC primes = (INT n) LIST: sieve(tl(one to(n)));
    show(primes(100))
END

将上述代码保存入文本文件primes.a68中,然后使用ALGOL 68 Genie执行它:

$ a68g primes.a68
 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

显著的语言元素

粗体符号和保留字

标准语言包含六十一个保留字,典型的用粗体字打印,并且其中一些还具有“简短”符号等价者:

MODEOPPRIOPROCFLEXHEAPLOCLONGREFSHORTBITSBOOLBYTESCHARCOMPLINTREALSEMASTRINGVOIDCHANNELFILEFORMATSTRUCTUNIONAT @,IS :=:, ISNT :/=:,OFr0TRUEFALSEEMPTYNIL ○,SKIP ~,
COMMENT  CO # ¢,PRAGMAT  PRCASE ~ IN ~ OUSE ~ IN ~ OUT ~ ESAC ( ~ | ~ |: ~ | ~ | ~ ),
FOR ~ FROM ~ TO ~ BY ~ WHILE ~ DO ~ ODIF ~ THEN ~ ELIF ~ THEN ~ ELSE ~ FI ( ~ | ~ |: ~ | ~ | ~ ),
PARBEGIN ~ END ( ~ ),GO TO  GOTOEXITr0

GO TO被当作两个保留字,未修订报告的语言还有保留字EITHERIS NOT结合。

单元:表达式

基本语言构造是“单元”(unit)。单元可以是“公式”、“闭合子句”、“例程正文”和某个技术上需要的那些构造(赋值、跳转、越过、空无)。技术术语“闭合子句”(enclosed clause)统一了某些固有的加括号的构造,在其他当代语言中被称为“块”、“do语句”、“switch语句”。在使用关键字的时候,通常使用介入关键字的反转字符序列来终结这个包围,比如:IF ~ THEN ~ ELSE ~ FICASE ~ IN ~ OUT ~ ESACFOR ~ WHILE ~ DO ~ OD。这种守卫命令语法被Stephen Bourne重新使用在常用的Unix Bourne shell之中。一个表达式还可以产生“多个值”,它是通过“并立子句”(collateral clause)从其他一些值构造出来的。这种构造看起来就像过程调用的参数包(pack)。

模态:声明

基本数据类型在ALGOL 68用语中叫做“模态”(mode),其原始声明符为:INTREALCOMPL复数)、BOOLCHARBITSBYTES。ALGOL 68不再定义longshortdouble这样的类型,而是提供了修饰符(modifier)LONGSHORT

  • BITSBOOL值的包装向量(packed vector)。
  • BYTESCHAR值的包装向量。
  • LONG – 声明INTREALCOMPL的大小为LONG
  • SHORT – 声明INTREALCOMPL的大小为SHORT

ALGOL 68提供了预置常量(prelude constant)如max reallong max real等来将程序适配到不同实现之中。

原始声明符还包括:COMPLEXGSTRINGFORMATFILEPIPEGCHANNELSEMA

  • STRINGCHAR值的FLEX(灵活)数组。
  • SEMA – 可以通过OP LEVEL初始化的信号量

所有变量都必须被声明,但是声明不必须先于第一次使用。例如:

INT n = 2;  # n被固定为常量2 #
INT m := 3; # m是新建的局部变量,它的值被初始化为3 #
# 这是REF INT m = LOC INT := 3;的简写 #
REAL avogadro = 6.02214076E23; # 阿伏伽德罗常数 #
LONG LONG REAL long long pi = 3.14159 26535 89793 23846 26433 83279 50288 41971 69399 37510;
COMPL square root of minus one = 0 I 1; # 复数0 + 1i #

复杂类型可以使用类型构造子REFSTRUCTUNIONPROC来创建自更简单的类型:

  • REF mode – 到类型mode的值的引用,类似于C/C++中和Pascal中的指针
  • STRUCT – 用来建造结构,类似于C/C++中的struct和Pascal中的recode
  • UNION – 用来建造联合,类似于C/C++和Pascal中的union
  • PROC – 用来指定过程,类似于C/C++中的函数和Pascal中的过程/函数。

具体例子可参见ALGOL 68与C++的比较英语Comparison of ALGOL 68 and C++

其他声明符号包括:FLEXHEAPLOCEVENTS

  • FLEX – 声明这个数组是灵活的,就是说它的长度可以按需要增长。
  • HEAP – 为变量从全局堆中分配一些空闲空间。
  • LOC – 为变量分配这个局部栈的一些空闲空间。

声明REAL x;只是REF REAL x = LOC REAL;语法糖。就是说,x实际上是“常量标识符”,它“引用到”一个新创建的局部REAL变量。

声明模态(类型)的名字可以使用MODE声明,它类似于C/C+中的typedef和Pascal中的type

 INT max = 99;
 MODE NEWMODE = [0:9][0:max]STRUCT (
     LONG REAL a, b, c, SHORT INT i, j, k, REF REAL r
 );

这类似于如下C99代码:

 const int max=99;
 typedef struct {
     double a, b, c; short i, j, k; float *r;
 } newmode[9+1][max+1];

对于ALGOL 68,只有模态指示符NEWMODE出现在等号的左侧,最值得注意的是,构造的制造和读取,是从左至右而不顾及优先级的。还有ALGOL 68数组的下界(lower bound)缺省的是1,但也可以是从-max intmax int的任何整数。

模态声明允许类型是递归的:直接或间接的依据自身来进行定义。这要服从一些限制,例如下列声明是非法的:

 MODE A = REF A
 MODE A = STRUCT (A a, B b)
 MODE A = PROC (A a) A

而下列声明是有效的:

 MODE A = STRUCT (REF A a, B b)
 MODE A = PROC (REF A a) REF A

强制:铸型

强制(coercion)依据三个要件,从被强制者(coercend)产生已强制者(coercee):在应用任何强制之前作为被强制者的一个先验模态,在这些强制之后作为已经强制者的一个后验模态,已强制者的的语法位置(position)或类属(sort)。强制是可以级联的(cascaded)。

有六种可能的强制,其术语为解过程化(deproceduring),解引用(dereferencing),联合化(uniting),扩大(widening)、成行(rowing)和弃置(voiding)。除了联合化之外,每种强制都在所关联的值之上,规制(prescribe)一个相应的动态效果。因此,可以使用强制来编程很多原始行动。

上下文强度 – 允许的强制:

  • 软(soft)– 解过程化。
  • 弱(weak) – 解引用或解过程化,产生一个名字。
  • 柔(meek)– 解引用或解过程化。
  • 硬(firm)– 柔强制,随后联合化。
  • 强(strong)– 硬强制,随后扩大、成行或弃置。

强制层级及例子

ALGOL 68有着上下文层级,它确定在程序中特定点之上可获得的强制的种类。这种上下文分为五个层次:

上下文 上下文位置 可获得的强制 在此上下文中强制例子
如下情况中的右手侧:
  • 标识符声明,如~之于REAL x = ~
  • 初始化,如~之于REAL x := ~

还有:

  • 调用的实际参数,如~之于PROC: sin(~)
  • 铸型(cast)的闭合子句,如~之于REAL(~)
  • 例程正文的单元
  • 产生VOID的语句
  • 平衡(balanced)子句的(除第一部分之外)的所有部分
  • 恒等关系的一侧,如~之于 ~ IS ~
解过程化 都软强制再解引用或解过程化产生一个名字 都弱强制再解引用或解过程化 都柔强制再联合化 都硬强制再扩大或成行或弃置

扩大出现在没有精度损失的情况下。例如:

  • LONG INTINT
  • REALINT
  • LONG REALREAL
  • COMPLREAL
  • 得 []BOOLBITS
  • STRINGBYTES

变量可以成行为长度为1的数组。例如:

  • 得 [1]INTINT
  • 得 [1]REALREAL
  • 公式的运算元,如~之于~ OP ~
  • 传输调用的参数
例子:

UNION(INT, REAL) var := 1

  • 剪标(trimscript),产生INT
  • 质询(enquiry),如~之于
    IF ~ THEN …… FIFROM ~ BY ~ TO ~ WHILE ~ DO …… OD
  • 调用的一级符号,如sin之于sin(x)
例子:
  • BOOLREF REF BOOL
  • INTREF REF REF INT
  • 分片的一级符号,如~之于~[1:99]
  • 选取的二级符号,如~之于value OF ~
例子:
  • REF INTREF REF INT
  • REF REALREF REF REF REAL
  • REF STRUCTREF REF REF REF STRUCT
赋值的左手侧,如~之于~ := …… 例子:
  • PROC REAL random的解过程化:random

关于一级符号(primary)、二级符号(secondary)、三级符号(tertiary)和四级符号(quaternary)可参见运算符优先级

PR和CO:指示和注释

指示(pragmat)在程序中的编译指导,典型的提示给编译器;在新近的语言中叫做“pragma”。例如:

PRAGMAT heap=32 PRAGMAT
PR heap=32 PR

注释可以按各种方式插入:

¢ 最初方式是在程序中增加两个美分符号 ¢
COMMENT "粗体"注释 COMMENT
CO 风格i注释 CO
# 风格ii注释 #
£ 针对英国键盘的横杠/英镑注释 £

一般而言,注释在ALGOL 68中不能嵌套。这个限制可以使用不同的注释分界符来绕过,比如只对临时代码删除使用井号。

表达式和复合语句

ALGOL 68成为了面向表达式编程语言英语Expression-oriented programming language赋值语句所返回的值是到目的地的引用。因此下列代码在ALGOL 68中是有效的:

 REAL half pi, one pi; one pi := 2*(half pi := 2*arc tan(1))

这种表示法也出现在C语言和Perl以及其他一些语言之中。注意在早期语言比如ALGOL 60FORTRAN中,在标识符中的空格是允许的,所以half pi是一个单一的标识符,因而无需采用蛇形命名法驼峰式大小写

另一个例子,要表达数学中f(i)i=1n的总和,下列ALGOL 68整数表达式就可胜任:

 (INT sum := 0; FOR i TO n DO sum +:= f(i) OD; sum)

注意,作为整数表达式,前面的代码块可以用在“整数值可以使用的任何上下”之中。代码块在ALGOL 68称为“系列子句”(serial clause),它返回其中被求值的最后一个表达式的值;这个概念也出现在LISP以及其他一些语言之上。

复合语句都终止于独特的闭括号:

  • IF选择子句:
 IF 条件 THEN 诸语句 [ ELSE 诸语句 ] FI
 “简短”形式:  ( 条件 | 诸语句 | 诸语句 )
 IF 条件1 THEN 诸语句 ELIF 条件2 THEN 诸语句 [ ELSE 诸语句 ] FI
 “简短”形式: ( 条件1 | 诸语句 |: 条件2 | 诸语句 | 诸语句 )

这种方案不仅避免了悬摆else英语dangling else问题,还避免了必须对嵌入的语句序列使用BEGINEND

  • CASE选择子句:
 CASE 开关 IN 诸语句, 诸语句, ... [ OUT 诸语句 ] ESAC
 “简短”形式:  ( 开关 | 诸语句, 诸语句, ... | 诸语句 )
 CASE 开关1 IN 诸语句, 诸语句, ... OUSE 开关2 IN 诸语句, 诸语句, ... [ OUT 诸语句 ] ESAC
 “简短”形式: ( 开关1 | 诸语句, 诸语句, ... |: 开关2 | 诸语句, 诸语句, ... | 诸语句 )

采用"简短"符号的选择子句的例子:

PROC days in month = (INT year, month) INT:
    (month|
     31,
     (year%*4 = 0 AND year%*100 /= 0 OR year%*400 = 0 | 29 | 28),
     31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    );

采用“粗体”符号的选择子句的例子:

PROC days in month = (INT year, month) INT:
    CASE month IN
        31,
        IF year MOD 4 EQ 0 AND year MOD 100 NE 0 OR year MOD 400 EQ 0 THEN 29 ELSE 28 FI,
        31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    ESAC;

混合了“粗体”和“简短”符号的选择子句的例子:

PROC days in month = (INT year, month) INT:
    CASE month IN
    #一月# 31,
    #二月# (year MOD 4 = 0 AND year MOD 100 /= 0 OR year MOD 400 = 0 | 29 | 28),
    #三月# 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 # 直到十二月 #
    ESAC;

Algol68允许开关具有类型要么INT要么(独有的)UNION。后者允许在UNION变量上施加强类型,参见后面的联合例子。

  • DO循环子句:
 [ FOR 索引 ] [ FROM 第一个 ] [ BY 增量 ] [ TO 最后一个 ] [ WHILE 条件  ] DO 诸语句 OD
 循环语句的极小化形式是DO 诸语句 OD

下面是这种“通用”循循的完整例子:

FOR i FROM 1 BY -22 TO -333 WHILE i*i /= 4444 DO ~ OD

这个构造有一些不寻常的方面:

  • 只有DO ~ OD部分是强制性的,在这种情况下循环将无限迭代。
  • 因此子句 TO 100 DO ~ OD,将只迭代100次。
  • WHILE“语法元素”允许编程者更早的从FOR循环中破出,例如:
INT sum sq := 0;
FOR i
WHILE
    print(("So far:", i, newline));
    sum sq /= 70**2
DO
    sum sq +:= i**2
OD

后续的对标准Algol68的扩展允许TO语法元素被替代为UPTODOWNTO来达成小优化。这些编译器还结合了:

  • UNTIL(C) – 用于更晚的循环终止。
  • FOREACH(S) – 用于并行的运算于数组之上。

进一步的例子可以在下面的代码例子中找到。

STRUCT、UNION和[:]:结构、联合和数组

ALGOL 68支持据于任意数目维度的数组,并且允许整体或部分横行或纵列的切片。

 MODE VECTOR = [1:3]    REAL;   # 向量MODE声明 #
 MODE MATRIX = [1:3,1:3]REAL;   # 矩阵MODE声明 #
 VECTOR v1  := (1,2,3);         # 数组变量初始化为 (1,2,3)  #
 []REAL v2   = (4,5,6);         # 常量数组,类型等价于VECTOR,边界是隐含的 #
 OP + = (VECTOR a, b) VECTOR:   # 二元OP即运算符定义 #
     (VECTOR out; FOR i FROM LWB a TO UPB a DO out[i] := a[i]+b[i] OD; out);
 MATRIX m := (v1, v2, v1+v2);
 print ((m[,2:]));              # 第二和第三纵列的切片 #

矩阵可以用任何一种方式定义,例如:

 REF VECTOR row = m[2,];  # 定义一个REF至第二横行 #
 REF VECTOR col = m[,2];  # 定义一个REF至第二纵列 #

ALGOL 68支持多字段结构STRUCT标签联合UNION。引用变量可以指向任何MODE,包括数组切片和结构字段。

作为递归模态的例子,下面是传统的链表的声明:

 MODE
     NODE = UNION (VOID, REAL, INT, COMPL, STRING),
     LIST = STRUCT (NODE val, REF LIST next);

对上述NODEUNION使用CASE的例子:

ALGOL68r0遵循1968年最终报告 ALGOL68r1遵循1973年修订报告
 NODE n := "1234";
 REAL r; INT i; COMPL c; STRING s
 CASE r,i,c,s CTAB n IN
     print(("real:", r)),
     print(("int:", i)),
     print(("compl:", c)),
     print(("string:", s))
 OUT print(("?:", n))
 ESAC
 NODE n := "1234";  # 或者 n := EMPTY; #
 CASE n IN
     (VOID):     print(("void:", "EMPTY")),
     (REAL r):   print(("real:", r)),
     (INT i):    print(("int:", i)),
     (COMPL c):  print(("compl:", c)),
     (STRING s): print(("string:", s))
     OUT         print(("?:", n))
 ESAC

PROC:过程

过程的PROC声明对参数和结果二者要求类型指定,如果没有则为VOID

 PROC max of real = (REAL a, b) REAL:
     IF a > b THEN a ELSE b FI;

或者使用条件语句的“简短”形式:

 PROC max of real = (REAL a, b) REAL: (a > b | a | b);

过程的返回值是在过程中求值的最后一个的表达式的值 。到过程的引用REF PROC也是允许的。提供了传引用调用参数来在形式参数列表中指定引用,比如REF REAL。下列例子定义一个过程,它将(作为参数而指定的)一个函数应用于一个数组的每个元素:

 PROC apply = (REF [] REAL a, PROC (REAL) REAL f):
     FOR i FROM LWB a TO UPB a DO a[i] := f(a[i]) OD

这种代码的简单性是在ALGOL 68的前身ALGOL 60中不能达成的。

OP:运算符

编程者可以定义新的运算符,并且这些自定义的和预定义的运算符二者都可以重载,并且它们的优先级可以由编码者变更。下列例子定义的运算符MAX具有二元和一元形式二者,一元形式在一个数组的元素之上进行扫描。

 PRIO MAX = 9;
  
 OP MAX = (INT a, b) INT: (a > b | a | b);
 OP MAX = (REAL a, b) REAL: (a > b | a | b);
 OP MAX = (COMPL a, b) COMPL: (ABS a > ABS b | a | b);
  
 OP MAX = ([]REAL a) REAL:
     (REAL out := a[LWB a];
      FOR i FROM LWB a + 1 TO UPB a DO (a[i] > out | out := a[i]) OD;
      out)

数组、过程、解引用和强制运算

PRIO ALGOL68r1运算 +ALGOL68r0−r1 +ALGOL68G
效果上 12
(一级符号)
解引用,解过程化(~,~),加下标[~],成行[~,],分片[~:~],大小指示LONGSHORT 过程化 柯里化(~,,,)DIAGTRNSPROWCOL
效果上 11
(二级符号)
OF(选取),LOCHEAP(生成器) → (选取) NEW(生成器)

这些符号在技术上不是运算符,它们转而被当作“关联着名字的单元”[27]

一元运算符

PRIO
(三级符号)
ALGOL68r1“杰出字符” +ALGOL68r1符号 +ALGOL68C,G +ALGOL68r0-r1
10 NOT,-,UPDOWNLWBUPBABSARGBINENTIERLENGLEVELODDREPRROUNDSHORTEN ¬ ~,↑,↓,⌊,⌈ NORMTRACETDETINV LWS ⎩,UPS ⎧,BTBCTB

关联着优先级的二元运算符

PRIO
(三级符号)
ALGOL68r1“杰出字符” +ALGOL68r1符号 +ALGOL68r0−r1
9 I +* ⊥ +× !
8 UP **,DOWNLWBUPBSHLSHR ↑,↓,⌊,⌈ ^ ××,LWS ⎩,UPS
7 *,/,OVER %,MOD %*,ELEM ×,÷,÷× ÷* %×,□ ÷:
6 -,+
5 LT <,LE <=,GE >=,GT > ≤,≥
4 EQ =,NE /= ≠ ¬= ~=
3 AND ∧ & /\
2 OR \/
1 MINUSAB -:=,PLUSAB +:=,TIMESAB *:=,DIVAB /:=,OVERAB %:=,MODAB %*:=,PLUSTO +=: ×:=,÷:=,÷×:=,÷*:=,%×:= MINUSPLUSTIMESDIVOVERBMODB ÷::=,PRUS

特殊细节:

  • 三级符号包括名字NIL
  • LWS:在ALGOL 68r0中,运算符LWS,在一个数组的这个维度的“下界状态”为固定的(fixed)的情况下, 二者都返回TRUE
  • UPS运算符针对“上界状态”。
  • LWBUPB运算符自动的可获得在一个数组的不同阶次(和MODE)的UNION之上,例如:UNION([]INT, [,]REAL, FLEX[,,,]CHAR)UPB

赋值和恒等关系等

这些符号在技术上不是运算符,它们转而被当作“关联着名字的单元”[27]

PRIO
(四级符号)
ALGOL68r1"杰出字符" +ALGOL68r1符号 +ALGOL68C,R +ALGOL68r0−r1
效果上 0 :=,IS :=:,ISNT :/=:,AT @,:,; :≠: :¬=: :~=: :=:=C,=:=R ..= .=,CT ::,CTAB ::=,IS NOT,..,.,

注意:四级符号包括名字SKIP~

IS(可替代为:=:)测试两个引用是否相等;ISNT(可替代为:/=:)测试两个引用是否不相等。

符号表示

1963年版的ASCII,在后来版本中,被替代为^被替代为_

“杰出字符”(worthy character)是1977年出版的ALGOL 68标准硬件表示报告出于可移植性而推荐的字符集中的字符[28]:

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9   " # $ % ' ( ) * + , - . / : ; < = > @ [ ] _ |

这反映了当年一些硬件不支持非ASCII字符的事实。

传输表示采用“杰出字符”时,“加上乘以”符号替代为I,“乘以的幂”符号\替代为E

具有APL符号的IBM 2741英语IBM 2741键盘。

ALGOL的“特殊”字符:

× ÷ ≤ ≥ ≠ ≡ ¬ ∧ ∨ ⊃ ↑ ⏨ ␣ ↓ → ⊥ ○ □ ⌊ ⌈ ⎩ ⎧ ¢

多数都可以在1965年出现的具有APL符号的IBM 2741英语IBM 2741键盘上找到。这些字符也是Unicode标准的一部分,并且在一些流行的字体中可获得到。

传输:输入和输出

传输(transput)是ALGOL 68用来称谓输入和输出设施的术语。它包括针对非格式化、格式化和二进制传输的预定义的过程。文件和其他传输设备以机器无关的方式来处理。下面的例子打印出一些非格式化的输出到“标准输出”设备:

 print ((newpage, "Title", newline, "Value of i is ",
     i, "and x[i] is ", x[i], newline))

注意预定义的过程newpagenewline作为实际参数而传送。

在ALGOL 68中“格式化传输”拥有自己的语法和模式(函数),具有嵌入在两个$字符之间的FORMAT。例如:

 printf (($2l"The sum is:"x, g(0)$, m + n)); # 其打印相同于下列: #
 print ((new line, new line, "The sum is:", space, whole(m + n, 0))

PAR:并行处理

ALGOL 68支持并行处理编程。使用关键字PAR,可以将“并立子句”转换成“并行子句”,这里的行动的同步使用信号量来控制。在ALOGL 68 Genie中并行行动被映射到线程上,如果它们在宿主操作系统上能获得到的话。例如:

PROC
    eat = VOID: (muffins -:= 1; print(("Yum!", new line))),
    speak = VOID: (words -:= 1; print(("Yak...", new line)));
 
INT muffins := 4, words := 8;
SEMA mouth = LEVEL 1;
 
PAR BEGIN
    WHILE muffins > 0 DO
        DOWN mouth;
        eat;
        UP mouth
    OD,
    WHILE words > 0 DO
        DOWN mouth;
        speak;
        UP mouth
    OD
END

未修订报告的语言

原本依据1968年最终报告的语言在“模态铸型” 的语法上有所不同,并且它拥有过程化(proceduring)这个特征,就是说,将一个项目的值强制成求值这个项目的一个过程。过程化意图进行惰性求值。最有用的应用是布尔运算符的短路求值:

OP ANDF = (BOOL a, PROC BOOL b) BOOL: (a | b | FALSE);
OP ORF = (BOOL a, PROC BOOL b) BOOL: (a | TRUE | b);

ANDF中,b只在aTRUE的情况下才求值。例如:

IF FALSE ANDF (print("Should not be executed"); TRUE) THEN ……

语言修订之后与编程者的预期相反,打印仍会执行,需要如下这样使打印不执行:

IF FALSE ANDF PROC BOOL: (print("Should not be executed"); TRUE) THEN ……

在语言修订之前,编程者可以通过使用叫做“gomma”的分号替代逗号(comma),从而决定一个过程的参数串行而非并立的求值。例如:

PROC test = (REAL a; REAL b): ……
test (x +:= 1, x);

这里保证第一个实际参数求值在第二个实际参数之前,但是在平常情况:

PROC test = (REAL a, b): ……
test (x +:= 1, x);

这时编译器可以按它喜好的次序来求值实际参数。

参见

注释

  1. ^ ALGOL 68 Genie. [2020-04-22]. (原始内容存档于2020-08-14). 
  2. ^ Dennis Ritchie. The Development of the C Language (PDF). April 1993 [2007-04-26]. (原始内容 (PDF)存档于2005-06-29). The scheme of type composition adopted by C owes considerable debt to Algol 68, although it did not, perhaps, emerge in a form that Algol’s adherents would approve of. The central notion I captured from Algol was a type structure based on atomic types (including structures), composed into arrays, pointers (references), and functions (procedures). Algol 68’s concept of unions and casts also had an influence that appeared later. …… a notation for type conversions (called ‘casts’ from the example of Algol 68) was invented to specify type conversions more explicitly. 
  3. ^ A History of C++: 1979−1991 (PDF). Page 12, 2nd paragraph: Algol68 [gave] operator overloading(§3.3.3), references (§3.3.4), and the ability to declare variables anywhere in a block (§3.3.1). March 1993 [2008-05-06]. (原始内容存档 (PDF)于2006-12-10). 
  4. ^ Interview with Guido van Rossum. July 1998 [2007-04-29]. (原始内容存档于2007-05-01). String slicing came from Algol-68 and Icon. 
  5. ^ 5.0 5.1 5.2 5.3 Revised Report on the Algorithmic Language Algol 68. 
  6. ^ Adriaan van Wijngaarden. Orthogonal design and description of a formal language (PDF). 1965. 
  7. ^ Hoare, C. a. R. Critique of ALGOL 68. ALGOL Bulletin. November 1968, 29: 27–29. I believe that the essential problem in the design of self-extending languages is in the design of the nucleus of built-in features, which the implementor will be expected to represent within the machine code of his computer. It is essential that this nucleus should have the properties: 1. Extreme simplicity and small size …… 2. Extreme efficiency of implementation …… I would therefore reckon that a language at about the level of FORTRAN would be a suitable choice for a nucleus. The language nucleus described in MR93 is far too elaborate; and some of its defects are listed in Appendix II. 
  8. ^ Dijkstra, E. W. To the Editor ALGOL 68 Mathematische Centrum. [2007-04-28]. (原始内容存档于2007-04-21). On account of the draft report my faith in WG.2.1 (at least in its present constitution) is very low. The draft report is thick and difficult, in fact too thick and too difficult to inspire much confidence. …… Size and complexity of the defining apparatus you needed terrify me. Being well-acquainted with your ingenuity I think it a safe assumption that ALGOL 68 as conceived can hardly be defined by significantly more concise and transparent means. …… I feel inclined to put the blame on the language you tried to define. If this is correct, WG.2.1 should return to its proper subject matter, viz. programming languages. 
  9. ^ Niklaus Wirth. ALGOL Colloqium – Closing Word. 1968. The implied and rather vague goal was the specification of a universal language, a sensible goal in 1960, even 1964, but an utopia in 1968; a goal which if pursued faithfully, invariably lead towards a monster language, a species of which there already exists a sample hardly worth nor possible to compete with. 
  10. ^ Learning Algol 68 Genie (PDF). Some claim that Ada is Algol 68’s successor but many dispute that. 
  11. ^ Adriaan van Wijngaarden. Generalized ALGOL (PDF). Symbolic Languages in Data Processing, Proc. Symp. Intl, Computation Center Rome, Gordon & Beach, New York. 1962. 
  12. ^ Van Wijngaarden, A.; Mailloux, B. J.; Peck, J.; Koster, C. H. A. Draft Report on the Algorithmic Language ALGOL 68. ALGOL Bulletin. 1 March 1968, (Sup 26): 1–84 [7 April 2023] –通过Mar. 1968. 
  13. ^ Report on the algorithmic language ALGOL 68. 1969. 
  14. ^ Sidney Marshall. J. E. L. Peck , 编. ALGOL 68 Implementation (PDF). Proceedings of the IFIP Working Conference on ALGOL 68 Implementation, Munich,: 239–243. July 20–24, 1970. 
    Sidney Marshall. On the implementation of ALGOL 68 (PDF). PhD Thesis, Dartmouth College. 1972. 
  15. ^ L. Ammeraal. An interpreter for simple Algol 68 Programs (PDF). 1973. 
  16. ^ Daniel M. Berry. The importance of implementation models in ALGOL 68: or how to discover the concept of necessary environment. 
  17. ^ Liverpool Software Gazette March 1980 (PDF). [2010-03-20]. (原始内容 (PDF)存档于2010-04-15). 
  18. ^ Revised report on the algorithmic language ALGOL 68 (PDF). 1976. 
  19. ^ Black, A. P.; Rayward-Smith, V. J. Proposals for ALGOL H - A Superlanguage of ALGOL 68. ALGOL Bulletin. 1 May 1978, (42): 36–49 [7 April 2023] –通过May. 1978. 
  20. ^ ALGOL 68 Version I Reference Manual (PDF). Control Data Services B.V., Rijswijk, Netherlands. 1976. 
  21. ^ ALGOL68 instruction at Oklahoma State University. 
  22. ^ "The Berlin ALGOL 68 implementation"
    An abstract ALGOL 68 machine and its application in a machine independent compiler – Springer. Springerlink.com. Retrieved on 2013-07-21.
  23. ^ Algol 68+, a superlanguage of Algol 68 for processing the standard-prelude (PDF). 1981. 
  24. ^ Hibbard, P.G. A Sublanguage of ALGOL 68. SIGPLAN Notices. May 1977, 12 (5): 71–79. S2CID 37914993. doi:10.1145/954652.1781177可免费查阅. 
  25. ^ a68mk2.zip 互联网档案馆存档,存档日期2006-08-29.
  26. ^ Open source Algol 68 implementations / algol68toc. Sourceforge.net. Retrieved on 2013-07-21.
  27. ^ 27.0 27.1 Units associated with names. 
  28. ^ Report on the Standard Hardware Representation of Algol 68. 16 May 1977. 

外部链接