ALGOL 68
编程范型 | 多范型:指令式,过程式,结构化,并发 |
---|---|
设计者 | 阿德里安·范·韦恩加登, B.J. Mailloux, J.E.L. Peck, C.H.A. Koster等人 |
发行时间 | 最终报告: 1968年 |
型态系统 | 静态、强类型、安全、结构式 |
网站 | Revised Report on the Algorithmic Language ALGOL 68 |
主要实作产品 | |
ALGOL 68C, ALGOL 68 Genie(新近[1]), ALGOL 68-R, ALGOL 68RS, ALGOL 68S, FLACC, 列宁格勒ALGOL 68, Odra ALGOL 68 | |
衍生副语言 | |
ALGOL 68r0 (最终报告:1968年), ALGOL 68r1 (修订报告:1973年) | |
启发语言 | |
ALGOL 60, ALGOL Y | |
影响语言 | |
C[2]、C++[3]、Bourne shell、KornShell、Bash、Steelman、Ada、Python[4]、Seed7、Mary、S3 |
ALGOL 68(源自英语:ALGOrithmic Language 1968的缩写),一种指令式编程语言,为ALGOL家族的成员,是官方上的ALGOL 60后继者。它设计的目标,是提供更广泛的应用,以及更严格的语法定义。
ALGOL 68的特征包括基于表达式的语法,用户声明的类型和结构/标记联合,变量和引用参数的引用模型,字符串、数组和矩阵的分片,以及并发。
概论
ALGOL 68由IFIP工作组2.1负责设计。1968年12月20日,IFIP工作组2.1通过了这个语法规范,并提交IFIP大会通过且出版。
ALGOL 68的定义使用了阿德里安·范·韦恩加登发明的一种数学形式主义的两级形式文法。Van Wijngaarden文法使用分别称为“超文法”和“元文法”的两组上下文无关文法规则,生成形成一个可能无限的产生式集合,而这些常规的产生式将识别特定的ALGOL 68程序;值得注意的是,它们能够表达在很多其他编程语言的技术标准中被标记为“语义”的那种要求,其他语言的语义必须用易致歧义的自然语言叙述来表达,并接着在编译器中实现为附加到形式语言解析器的“特设”代码。
ALGOL 68设计的主要目标和原则为:
ALGOL 68曾受到批评,最突出的是来自其设计委员会的一些成员比如C. A. R. Hoare[7],还有ALGOL 60编译器作者比如Edsger Dijkstra[8],它抛弃了ALGOL 60的简单性,成为了复杂或过于笼统的想法的载体,不能使编译器作者的任务变得更轻易些,与刻意保持简单的同时代(竞争)者如C、S-algol和Pascal形成了鲜明对比。
在1970年,ALGOL 68-R成为了第一个投入工作的ALGOL 68编译器。
在1973年9月确定的修订版本中,省略了特定特征比如过程化、gomma和形式边界[5]。
Stephen R. Bourne是ALGOL 68修订委员会成员,他选取了它的一些想法到他的Bourne shell之中。
ALGOL 68的语言定义出版后的文本长达两百多页并充斥着非标准术语,这种复杂性使得编译器实现变得困难,故而它曾被称为“没有实现也没有用户”。这么说只是部分真实的,ALGOL 68曾应用于一些小众市场,特别是流行于英国的国际计算机有限公司(ICL)的机器之上,还有在教学角色之上。在这些领域之外,其使用相对有限。
尽管如此,ALGOL 68对计算机科学领域的贡献是深刻、广泛而持久的,虽然这些贡献大多只是在它们于后来开发的编程语言中重现之时才被公开认可。很多语言是为了应对这门语言的复杂性而专门开发的,其中最著名的是Niklaus Wirth的ALGOL W和Pascal[9],或者是针对特定角色而重新实现的,比如有些人认为Ada可以看作ALGOL 68的后继者[10]。
1970年代的很多语言可以追溯其设计至ALGOL 68,选取一些特征,并放弃被认为太复杂或超出给定角色范围的其他特征。其中就有C语言,它受到ALGOL 68的直接影响,特别是它的强类型和结构。多数现代语言都至少可以追溯其部分语法至要么C语言要么Pascal,因而很多语言可直接或间接的经由C语言而追溯至ALGOL 68。
规定和实现时间线
名称 | 年 | 用途 | 国家 | 描述 | 目标CPU | 属主/许可证 | 实现语言 |
---|---|---|---|---|---|---|---|
广义ALGOL | 1962 | 科学 | 荷兰 | 广义文法的ALGOL[11] | |||
ALGOL 68DR | 1968 | 草案 | IFIP WG 2.1草案报告[12] | ||||
ALGOL 68r0 | 1968 | 标准 | IFIP WG 2.1最终报告[13] | ||||
ALGOL 68-R | 1970 | 军用 | 英国 | GEORGE 3之下的ALGOL 68 | ICL 1900 | 皇家雷达研究所 | ALGOL 60 |
DTSS ALGOL 68 | 1970 | 美国 | Dartmouth分时系统的ALGOL 68[14] | GE-635 | 达特茅斯学院 | ||
Mini ALGOL 68 | 1973 | 研究 | 荷兰 | 针对简单ALGOL 68程序的解释器[15] | 可移植解释器 | 荷兰数学中心 | ALGOL 60 |
OREGANO | 1973 | 研究 | 美国 | 实践“实现模型的重要性。”[16] | 加州大学洛杉矶分校 | ||
ALGOL 68C | 1975 | 科学 | 英国 | 剑桥ALGOL 68 | ICL,IBM System/360,PDP-10和Unix,Telefunken,Tesla和Z80(1980年)[17] | 剑桥大学 | ALGOL 68C |
ALGOL 68r1 | 1975 | 标准 | IFIP WG 2.1修订报告[18] | ||||
Algol H | 1975 | 实验等 | 英国 | 对ALGOL 68的模态系统提议了扩展[19] | ALGOL W | ||
CDC ALGOL 68 | 1975 | 科学 | 美国 | 完全实现的ALGOL 68[20] | CDC 6000系列,CDC Cyber | 控制数据公司 | |
Odra ALGOL 68 | 1976 | 实用 | 苏联/ 波兰 | Odra 1204/IL | ALGOL 60 | ||
俄克拉何马ALGOL 68 | 1976 | 编程指导 | 美国 | 俄克拉何马州立大学实现[21] | IBM 1130和System/370 Model 158 | 俄克拉何马州立大学 | ANSI Fortran 66 |
柏林ALGOL 68 | 1977 | 研究 | 德国 | 柏林ALGOL 68实现[22] | 抽象ALGOL 68机器 – 机器无关编译器 | 柏林工业大学 | CDL 2 |
FLACC | 1977 | 多用途 | 加拿大 | 具有调试特征的修订报告完整实现 | System/370 | 租用,Chion公司 | 汇编 |
ALGOL 68RS | 1977 | 军用 | 英国 | 可移植编译器 | ICL 2900系列,Multics,VMS和C生成器(1993年) | 皇家信号与雷达研究所 | ALGOL 68RS |
ALGOL 68-RT | 1979 | 科学 | 英国 | 并行ALGOL 68-R | |||
ALGOL 68+ | 1980 | 科学 | 荷兰 | 提议的ALGOL 68的超语言[23] | |||
M-220 ALGOL 68 | 苏联 | M-220 | EPSILON | ||||
列宁格勒ALGOL 68 | 1980 | 电信 | 苏联 | 完全语言 + 模块 | IBM,DEC,CAMCOH,PS 1001和PC | ||
交互式ALGOL 68 | 1983 | 英国 | 增量编译 | PC | 非商业共享软件 | ||
ALGOL 68S | 1985 | 科学 | 英国 | ALGOL 68的子集语言[24] | Sun-3,Sun SPARC(在SunOS 4.1和Solaris 2下),Atari ST(在GEMDOS下),Acorn Archimedes(在RISC OS下),VAX-11(在Ultrix-32下) | 曼彻斯特维多利亚大学 | BLISS |
MK2 交互式ALGOL 68 | 1992 | 英国 | 增量编译 | PC | 非商业共享软件[25] | ||
A68toC[26] | 1993 | 电子 | 英国 | 基于源自1985年ELLA ALGOL 68RS的ctrans | 可移植C生成器 | 国防研究局的皇冠版权开源软件 | 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
显著的语言元素
粗体符号和保留字
标准语言包含六十一个保留字,典型的用粗体字打印,并且其中一些还具有“简短”符号等价者:
MODE,OP,PRIO,PROC, FLEX,HEAP,LOC,LONG,REF,SHORT, BITS,BOOL,BYTES,CHAR,COMPL,INT,REAL,SEMA,STRING,VOID, CHANNEL,FILE,FORMAT,STRUCT,UNION, AT @,IS :=:, ISNT :/=:,OF →r0,TRUE,FALSE,EMPTY,NIL ○,SKIP ~, COMMENT CO # ¢,PRAGMAT PR, CASE ~ IN ~ OUSE ~ IN ~ OUT ~ ESAC ( ~ | ~ |: ~ | ~ | ~ ), FOR ~ FROM ~ TO ~ BY ~ WHILE ~ DO ~ OD, IF ~ THEN ~ ELIF ~ THEN ~ ELSE ~ FI ( ~ | ~ |: ~ | ~ | ~ ), PAR,BEGIN ~ END ( ~ ),GO TO GOTO,EXIT □r0。
GO TO被当作两个保留字,未修订报告的语言还有保留字EITHER和IS NOT结合。
单元:表达式
基本语言构造是“单元”(unit)。单元可以是“公式”、“闭合子句”、“例程正文”和某个技术上需要的那些构造(赋值、跳转、越过、空无)。技术术语“闭合子句”(enclosed clause)统一了某些固有的加括号的构造,在其他当代语言中被称为“块”、“do语句”、“switch语句”。在使用关键字的时候,通常使用介入关键字的反转字符序列来终结这个包围,比如:IF ~ THEN ~ ELSE ~ FI
、CASE ~ IN ~ OUT ~ ESAC
和FOR ~ WHILE ~ DO ~ OD
。这种守卫命令语法被Stephen Bourne重新使用在常用的Unix Bourne shell之中。一个表达式还可以产生“多个值”,它是通过“并立子句”(collateral clause)从其他一些值构造出来的。这种构造看起来就像过程调用的参数包(pack)。
模态:声明
基本数据类型在ALGOL 68用语中叫做“模态”(mode),其原始声明符为:INT、REAL、COMPL(复数)、BOOL、CHAR、BITS和BYTES。ALGOL 68不再定义long
、short
和double
这样的类型,而是提供了修饰符(modifier)LONG和SHORT。
- BITS – BOOL值的包装向量(packed vector)。
- BYTES – CHAR值的包装向量。
- LONG – 声明INT、REAL或COMPL的大小为LONG。
- SHORT – 声明INT、REAL或COMPL的大小为SHORT。
ALGOL 68提供了预置常量(prelude constant)如max real
和long max real
等来将程序适配到不同实现之中。
原始声明符还包括:COMPLEXG、STRING、FORMAT、FILE、PIPEG、CHANNEL和SEMA。
- STRING – CHAR值的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 #
复杂类型可以使用类型构造子REF、STRUCT、UNION和PROC来创建自更简单的类型:
- REF
mode
– 到类型mode
的值的引用,类似于C/C++中和Pascal中的指针。 - STRUCT – 用来建造结构,类似于C/C++中的
struct
和Pascal中的recode
。 - UNION – 用来建造联合,类似于C/C++和Pascal中的
union
。 - PROC – 用来指定过程,类似于C/C++中的函数和Pascal中的过程/函数。
具体例子可参见ALGOL 68与C++的比较。
其他声明符号包括:FLEX、HEAP、LOC、EVENTS。
- 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 int
到max 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有着上下文层级,它确定在程序中特定点之上可获得的强制的种类。这种上下文分为五个层次:
上下文 | 上下文位置 | 可获得的强制 | 在此上下文中强制例子 | ||||
---|---|---|---|---|---|---|---|
软 | 弱 | 柔 | 硬 | 强 | |||
强 | 如下情况中的右手侧:
还有:
|
解过程化 | 都软强制再解引用或解过程化产生一个名字 | 都弱强制再解引用或解过程化 | 都柔强制再联合化 | 都硬强制再扩大或成行或弃置 |
扩大出现在没有精度损失的情况下。例如:
变量可以成行为长度为1的数组。例如:
|
硬 |
|
例子:
| |||||
柔 |
|
例子:
| |||||
弱 |
|
例子:
| |||||
软 | 赋值的左手侧,如~ 之于~ := ……
|
例子:
|
关于一级符号(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成为了面向表达式编程语言,赋值语句所返回的值是到目的地的引用。因此下列代码在ALGOL 68中是有效的:
REAL half pi, one pi; one pi := 2*(half pi := 2*arc tan(1))
这种表示法也出现在C语言和Perl以及其他一些语言之中。注意在早期语言比如ALGOL 60和FORTRAN中,在标识符中的空格是允许的,所以half pi
是一个单一的标识符,因而无需采用蛇形命名法或驼峰式大小写。
另一个例子,要表达数学中f(i)
从i=1
到n
的总和,下列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问题,还避免了必须对嵌入的语句序列使用BEGIN
和END
。
- 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语法元素被替代为UPTO和DOWNTO来达成小优化。这些编译器还结合了:
- 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);
对上述NODE
的UNION使用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 (一级符号) |
解引用,解过程化(~,~) ,加下标[~] ,成行[~,] ,分片[~:~] ,大小指示LONG和SHORT
|
过程化 | 柯里化(~,,,) ,DIAG,TRNSP,ROW,COL
|
效果上 11 (二级符号) |
OF(选取),LOC和HEAP(生成器) | → (选取) | NEW(生成器) |
这些符号在技术上不是运算符,它们转而被当作“关联着名字的单元”[27]。
一元运算符
PRIO (三级符号) |
ALGOL68r1“杰出字符” | +ALGOL68r1符号 | +ALGOL68C,G | +ALGOL68r0-r1 |
---|---|---|---|---|
10 | NOT,-,UP,DOWN,LWB,UPB,ABS,ARG,BIN,ENTIER,LENG,LEVEL,ODD,REPR,ROUND,SHORTEN | ¬ ~,↑,↓,⌊,⌈ | NORM,TRACE,T,DET,INV | LWS ⎩,UPS ⎧,BTB,CTB |
关联着优先级的二元运算符
PRIO (三级符号) |
ALGOL68r1“杰出字符” | +ALGOL68r1符号 | +ALGOL68r0−r1 |
---|---|---|---|
9 | I +* | ⊥ +× | ! |
8 | UP **,DOWN,LWB,UPB,SHL,SHR | ↑,↓,⌊,⌈ | ^ ××,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 +=: | ×:=,÷:=,÷×:=,÷*:=,%×:= | MINUS,PLUS,TIMES,DIV,OVERB,MODB ÷::=,PRUS |
特殊细节:
- 三级符号包括名字NIL和
○
。 - LWS:在ALGOL 68r0中,运算符LWS和
⎩
,在一个数组的这个维度的“下界状态”为固定的(fixed)的情况下, 二者都返回TRUE。 - UPS和
⎧
运算符针对“上界状态”。 - LWB和UPB运算符自动的可获得在一个数组的不同阶次(和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(可替代为:/=:
)测试两个引用是否不相等。
符号表示
“杰出字符”(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。
ALGOL的“特殊”字符:
- × ÷ ≤ ≥ ≠ ≡ ¬ ∧ ∨ ⊃ ↑ ⏨ ␣ ↓ → ⊥ ○ □ ⌊ ⌈ ⎩ ⎧ ¢
多数都可以在1965年出现的具有APL符号的IBM 2741键盘上找到。这些字符也是Unicode标准的一部分,并且在一些流行的字体中可获得到。
传输:输入和输出
传输(transput)是ALGOL 68用来称谓输入和输出设施的术语。它包括针对非格式化、格式化和二进制传输的预定义的过程。文件和其他传输设备以机器无关的方式来处理。下面的例子打印出一些非格式化的输出到“标准输出”设备:
print ((newpage, "Title", newline, "Value of i is ", i, "and x[i] is ", x[i], newline))
注意预定义的过程newpage
和newline
作为实际参数而传送。
在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
只在a
为TRUE的情况下才求值。例如:
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);
这时编译器可以按它喜好的次序来求值实际参数。
参见
- ALGOL 60
- ALGOL Y
- ALGOL N
- ALGOL 68C
- C
- C++
- ALGOL 68与C++的比较
- Bourne shell
- Bash (Unix shell)
注释
- ^ ALGOL 68 Genie. [2020-04-22]. (原始内容存档于2020-08-14).
- ^ 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.
- ^ 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).
- ^ Interview with Guido van Rossum. July 1998 [2007-04-29]. (原始内容存档于2007-05-01).
String slicing came from Algol-68 and Icon.
- ^ 5.0 5.1 5.2 5.3 Revised Report on the Algorithmic Language Algol 68.
- ^ Adriaan van Wijngaarden. Orthogonal design and description of a formal language (PDF). 1965.
- ^ 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.
- ^ 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.
- ^ 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.
- ^ Learning Algol 68 Genie (PDF).
Some claim that Ada is Algol 68’s successor but many dispute that.
- ^ Adriaan van Wijngaarden. Generalized ALGOL (PDF). Symbolic Languages in Data Processing, Proc. Symp. Intl, Computation Center Rome, Gordon & Beach, New York. 1962.
- ^ 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.
- ^ Report on the algorithmic language ALGOL 68. 1969.
- ^ 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. - ^ L. Ammeraal. An interpreter for simple Algol 68 Programs (PDF). 1973.
- ^ Daniel M. Berry. The importance of implementation models in ALGOL 68: or how to discover the concept of necessary environment.
- ^ Liverpool Software Gazette March 1980 (PDF). [2010-03-20]. (原始内容 (PDF)存档于2010-04-15).
- ^ Revised report on the algorithmic language ALGOL 68 (PDF). 1976.
- ^ 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.
- ^ ALGOL 68 Version I Reference Manual (PDF). Control Data Services B.V., Rijswijk, Netherlands. 1976.
- ^ ALGOL68 instruction at Oklahoma State University.
- ^ "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. - ^ Algol 68+, a superlanguage of Algol 68 for processing the standard-prelude (PDF). 1981.
- ^ Hibbard, P.G. A Sublanguage of ALGOL 68. SIGPLAN Notices. May 1977, 12 (5): 71–79. S2CID 37914993. doi:10.1145/954652.1781177 .
- ^ a68mk2.zip 互联网档案馆的存档,存档日期2006-08-29.
- ^ Open source Algol 68 implementations / algol68toc. Sourceforge.net. Retrieved on 2013-07-21.
- ^ 27.0 27.1 Units associated with names.
- ^ Report on the Standard Hardware Representation of Algol 68. 16 May 1977.
外部链接
- Revised Report on the Algorithmic Language ALGOL 68(页面存档备份,存于互联网档案馆) The official reference for users and implementors of the language (large pdf file, scanned from Algol Bulletin)
- Revised Report on the Algorithmic Language ALGOL 68(页面存档备份,存于互联网档案馆) Hyperlinked HTML version of the Revised Report
- A Tutorial on Algol 68, by Andrew S. Tanenbaum, in Computing Surveys, Vol. 8, No. 2, June 1976, with Corrigenda (Vol. 9, No. 3, September 1977)
- Algol 68 Genie – a GNU GPL Algol 68 compiler-interpreter(页面存档备份,存于互联网档案馆)
- Open source Algol 68 implementations, on SourceForge(页面存档备份,存于互联网档案馆)
- Algol68 Standard Hardware representation (.pdf)(页面存档备份,存于互联网档案馆)
- Из истории создания компилятора с Алгол 68(页面存档备份,存于互联网档案馆)
- Algol 68 – 25 Years in the USSR(页面存档备份,存于互联网档案馆)
- Система программ динамической поддержки для транслятора с Алгол 68
- C history with Algol68 heritage
- McJones, Paul, "Algol 68 implementations and dialects"(页面存档备份,存于互联网档案馆), Software Preservation Group, Computer History Museum, 2011-07-05
- Web enabled ALGOL 68 compiler for small experiments