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

Quick Facts 编程范型, 设计者 ...
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)
Close

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

概论

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[9]和形式边界[5]

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

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

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

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

规定和实现时间线

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

样例代码

下面的样例代码实现了埃拉托斯特尼筛法来找到小于等于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)),
        error = (STRING s) VOID:
            (print((newline, " error: ", s, newline)); GOTO stop),
        hd = (LIST l) INT: (l IS NIL | error("hd NIL"); SKIP | h OF l),
        tl = (LIST l) LIST: (l IS NIL | error("tl NIL"); SKIP | t OF l),
        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 @,EITHERr0IS :=:,ISNT  IS NOTr0 :/=: :≠:,OFr0TRUEFALSEEMPTYNIL ○,SKIP ~,
CO  COMMENT ¢,PR  PRAGMATCASE ~ IN ~ OUSE ~ IN ~ OUT ~ ESAC ( ~ | ~ |: ~ | ~ | ~ ),
FOR ~ FROM ~ TO ~ BY ~ WHILE ~ DO ~ ODIF ~ THEN ~ ELIF ~ THEN ~ ELSE ~ FI ( ~ | ~ |: ~ | ~ | ~ ),
PARBEGIN ~ END ( ~ ),GO TO  GOTOEXITr0

单元:表达式

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

模态:声明

基本数据类型在ALGOL 68用语中叫做“模态”(mode),包括:REALINTCOMPL复数)、BOOLCHARBITSBYTES。例如:

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

然而,声明REAL x;只是REF REAL x = LOC REAL;语法糖。就是说,x实际上是“常量标识符”,它“引用到”一个新创建的局部REAL变量。 进一步的,不再定义floatdouble,或者longshort等,ALGOL 68提供了修饰符(modifier),以目前常见的double为例,它们将写为LONG REALLONG LONG REAL。提供了预置常量(prelude constant)max realmin long int来将程序适配到不同实现之中。

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

原始声明符:INTREALCOMPLCOMPLEXGBOOLCHARSTRINGBITSBYTESFORMATFILEPIPEGCHANNELSEMA

  • BITSBOOL值的包装向量(packed vector)。
  • BYTESCHAR值的包装向量。
  • STRINGCHAR值的FLEX(灵活)数组。
  • SEMA – 可以通过OP LEVEL初始化的信号量

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

  • 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++

其他声明符号包括:FLEXHEAPLOCREFLONGSHORTEVENTS

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

声明模态(类型)的名字可以使用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
 );

这类似于如下C语言代码:

  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)。除了单位化之外,每种强制都在所关联的值之上规制一个相应的动态效果。因此,很多原始行动可以使用强制来编程。

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

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

强制层级及例子

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

More information 上下文, 上下文位置 ...
上下文 上下文位置 可获得的强制 在此上下文中强制例子
如下情况中的右手侧:
  • 标识符声明,如~之于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
Close

关于一级符号(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)

注意,作为整数表达式,前面的代码块可以用在“整数值可以使用的任何上下”之中。代码块返回它被求值的最后一个表达式的值;这个概念也出现在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 ∧ year÷×100≠0  ∨  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;   # vector MODE声明 (即类型定义)  #
 MODE MATRIX = [1:3,1:3]REAL;   # matrix 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 ⌊a TO ⌈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的例子:

More information Algol68r0遵循1968年最终报告, Algol68r1遵循1973年修订报告 ...
Algol68r0遵循1968年最终报告 Algol68r1遵循1973年修订报告
 NODE n := "1234";
 REAL r; INT i; COMPL c; STRING s
 CASE r,i,c,s::=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
Close

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);

PROC的返回值是在过程中求值的最后一个的表达式的值 。到过程的引用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)

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

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

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

一元运算符

More information PRIO (三级符号), Algol68“杰出字符”r0&r1 ...
PRIO
(三级符号)
Algol68“杰出字符”r0&r1 +Algol68r0&r1 +Algol68C,G +Algol68r0
10 NOT ~,UPDOWNLWBUPB,-,ABSARGBINENTIERLENGLEVELODDREPRROUNDSHORTEN ¬,↑,↓,⌊,⌈ NORMTRACETDETINV LWSUPS,⎩,⎧,BTBCTB
Close

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

More information PRIO (三级符号), Algol68“杰出字符”r0&r1 ...
PRIO
(三级符号)
Algol68“杰出字符”r0&r1 +Algol68r0&r1 +Algol68r0
9 +*,I +×,⊥ !
8 SHLSHR,**,UPDOWNLWBUPB ↑,↓,⌊,⌈ ××,^, LWSUPS,⎩,⎧
7 *,/,%,OVER,%*,MODELEM ×,÷,÷×,÷*,%×,□ ÷:
6 -,+
5 <,LT,<=,LE,>=,GE,>,GT ≤,≥
4 EQ =,NE ~= /= ≠,¬=
3 &, AND /\
2 OR \/
1 MINUSABPLUSABTIMESABDIVABOVERABMODABPLUSTO,-:=,+:=,*:=,/:=,%:=,%*:=,+=: ×:=,÷:=,÷×:=,÷*:=,%×:= MINUSPLUSDIVOVERBMODB,÷::=,PRUS
Close

特殊细节:

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

赋值和恒等关系等

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

More information PRIO (四级符号), Algol68"杰出字符"r0&r1 ...
PRIO
(四级符号)
Algol68"杰出字符"r0&r1 +Algol68r0&r1 +Algol68C,G,R +Algol68r0
效果上 0 =:=,IS :=:,ISNT :/=:,:~=:,AT @,:,; :≠: :¬=: =:=:=C,=:=R =..=,.=,CT,::,CTAB,::=,..,IS NOT,.,
Close

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

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

特殊字符

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

多数ALGOL的“特殊”字符(⊂, ≡, ␣, ×, ÷, ≤, ≥, ≠, ¬, ⊃, ≡, ∨, ∧, →, ↓, ↑, ⌊, ⌈, ⎩, ⎧, ⊥, ⏨, ¢, ○, □),可以在具有APL符号的IBM 2741英语IBM 2741键盘上找到;故而这些字符在1960年代中期起草ALGOL 68的时候就能获得到。这些字符也是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);

其中的b只有在a为真的情况下才求值。

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

PROC test = (REAL a; REAL b) :...
...
test (x PLUS 1, x);

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

PROC test = (REAL a, b) :...
...
test (x PLUS 1, x);

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

参见

注释

外部链接

Wikiwand in your browser!

Seamless Wikipedia browsing. On steroids.

Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.

Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.