ALGOL 68

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

ALGOL 68的特征包括面向表达式编程语言的语法，用户声明的类型和结构与标签联合类型，变量与引用参数的引用模型，可变长数组和字符串、数组与矩阵的阵列分片，用户定义的运算符和运算符重载，高阶函数与匿名函数，以及并发。

## 概论

IFIP工作组2.1在1964年3月达成一致，要制定ALGOL 60的两个后续语言标准：ALGOL X，它是具有增补的强类型和Euler语言中的树或列表的ALGOL语言重新定义；和ALGOL Y，它具有LISP的同像性风格修改自身程序能力。经过多次会议研讨针对ALGOL X的提案之后，1968年12月20日，IFIP工作组2.1正式通过了ALGOL 68最终报告，并在1969年1月将其提交给了信息处理国际联盟大会，在1969年3月，IFIP大会经过邮件投票授权出版此报告。

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

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

- 描述的完备性和清晰性。
- 设计的正交性。
- 安全性。
- 静态的模态（即类型）检查。
- 模态无关的解析。
- 分立编译。
- 循环优化。
- 表示于极小化和更大的字符集。

在1970年，ALGOL 68-R成为了第一个投入工作的ALGOL 68编译器。在1973年9月确定并于1975年出版的修订报告中，省略了特定特征比如过程化、gomma和形式边界。Stephen R. Bourne是ALGOL 68修订委员会成员，他选取了它的一些想法到他的Bourne shell之中。

ALGOL 68曾受到激烈的批评，最突出的是来自其设计委员会的一些成员比如C. A. R. Hoare，还有ALGOL 60编译器作者比如Edsger Dijkstra，它获评为抛弃了ALGOL 60的简单性，成为了复杂或过于笼统的想法的载体。ALGOL 68与刻意保持简单的同时代（竞争）者如C、S-algol和Pascal形成了鲜明对比。

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

尽管如此，ALGOL 68对计算机科学领域的贡献是深刻、广泛而持久的，虽然这些贡献大多只是在它们于后来开发的编程语言中重现之时才被公开认可。很多语言是为了应对设计这门语言时所采用的形式化方法导致的复杂性而专门开发的，其中最著名的是Niklaus Wirth的采用附缀文法的ALGOL W和作为其后继者的采用扩展巴科斯-瑙尔范式（EBNF）的Pascal；或者是针对特定角色而重新实现的，比如有些人认为Ada可以看作ALGOL 68的后继者。

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

ALGOL 68项目的完整历史可参见Charles H. Lindsey的《A History of ALGOL 68》。ALGOL 68语言的长篇阐述可参见Dr. Sian Mountbatten的《Programming ALGOL 68 Made Easy》，或者Marcel van der Veer的《Learning ALGOL 68 Genie》。

## 规定和实现时间线

名称｜年｜国家｜描述｜目标CPU/平台｜属主/许可证｜实现语言

Generalized ALGOL｜1962｜荷兰｜广义ALGOL｜荷兰数学中心

ALGOL XDP｜1966｜ALGOL X草拟提案｜IFIP工作组2.1

ALGOL 68DR｜1968｜ALGOL 68草案报告｜IFIP工作组2.1

ALGOL 68r0｜1968｜ALGOL 68最终报告｜IFIP工作组2.1

ALGOL 68-R｜1970｜英国｜GEORGE操作系统之下的ALGOL 68｜ICT 1900系列｜皇家雷达研究所｜ALGOL 60

DTSS ALGOL 68｜1970｜美国｜Dartmouth分时系统的ALGOL 68｜GE-600系列｜达特茅斯学院

Mini ALGOL 68｜1973｜荷兰｜针对简单ALGOL 68程序的解释器｜可移植解释器｜荷兰数学中心｜ALGOL 60

OREGANO｜1973｜美国｜实践“实现模型的重要性。”｜加州大学洛杉矶分校

M-220 ALGOL 68｜1974｜苏联｜使用EPSILON语言在M系列计算机上实现ALGOL 68｜M系列计算机｜EPSILON语言

ALGOL 68C｜1975｜英国｜剑桥大学ALGOL 68实现｜国际计算机有限公司，IBM System/360，PDP-10和Unix，Telefunken TR440/TR445，Tesla a.s. 200和Z80（1980年）｜剑桥大学｜ALGOL 68C

ALGOL 68r1｜1975｜ALGOL 68修订报告｜IFIP工作组2.1

ALGOL 68 H｜1975｜加拿大 荷兰｜ALGOL 68编译器｜阿尔伯塔大学，荷兰数学中心｜ALGOL W

CDC ALGOL 68｜1975｜美国｜完全实现的ALGOL 68｜CDC 6000系列，CDC Cyber｜控制数据公司

Odra ALGOL 68｜1976｜苏联 波兰｜Odra计算机 1204/IL｜ALGOL 60

Oklahoma ALGOL 68｜1976｜美国｜俄克拉何马州立大学ALGOL 68实现｜IBM 1130和IBM System/370｜俄克拉何马州立大学｜ANSI Fortran 66

Berlin ALGOL 68｜1977｜德国｜柏林工业大学ALGOL 68实现｜基于抽象ALGOL 68机器的机器无关编译器｜柏林工业大学｜编译器描述语言

FLACC｜1977｜加拿大｜具有调试特征的修订报告完整实现｜System/370｜租用，Chion公司｜汇编

ALGOL 68RS｜1977｜英国｜可移植编译器｜ICL 2900系列，Multics，VMS和C生成器（1993年）｜皇家信号与雷达研究所｜ALGOL 68RS

ALGOL 68 MR｜1978｜ALGOL 68的模块和分立编译规定｜IFIP工作组2.1

ALGOL 68-RT｜1979｜英国｜并行ALGOL 68-R

Leningrad ALGOL 68｜1980｜苏联｜列宁格勒国立大学开发的完全语言加上模块系统｜IBM，DEC，CAMCOH，PS 1001和PC

交互式ALGOL 68｜1983｜英国｜增量编译，1992年再版MK2｜PC｜非商业共享软件

ALGOL 68S｜1985｜英国 美国｜ALGOL 68的子集语言｜Sun-3，Sun SPARC（在SunOS 4.1和Solaris 2下），Atari ST（在GEMDOS下），Acorn Archimedes（在RISC OS下），VAX-11（在Ultrix下）｜利物浦大学，卡内基·梅隆大学，曼彻斯特大学｜BLISS，Pascal

Rutgers ALGOL 68｜1990｜美国 匈牙利｜Mini ALGOL 68解释器后续版本｜可移植解释器｜写于罗格斯大学的非商业开源软件｜C

Algol68toC｜1993｜英国｜基于源自1985年ELLA语言ALGOL 68RS的ctrans｜可移植C生成器｜国防研究局的皇冠版权开源软件｜ALGOL 68RS

ALGOL 68 Genie｜2001｜荷兰｜完全语言包括标准的并立子句｜可移植解释器；2010年版本2之后，具有可选的选定单元的编译｜GNU GPL｜C

Algol68FrontEnd in GCC｜2025｜西班牙｜GCC中的ALGOL 68前端｜跨平台｜GNU GPL｜C/C++

## 样例代码

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

```bash
BEGIN # ALGOL68的素数筛法，基于链表实现 #
    MODE
        NODE = STRUCT (INT h, REF NODE t),
        LIST = REF NODE;
    OP CONS = (INT n, LIST l) LIST: HEAP NODE := NODE (n, l);
    PRIO CONS = 9;
    PROC one to = (INT n) LIST:
        (PROC fn = (INT m) LIST: (m > n | NIL | m CONS fn(m + 1));
         fn(1));
    PROC error = (STRING s) VOID:
        (print((newline, " error: ", s, newline)); 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:
    BEGIN
        PROC fn = (LIST m) LIST:
            IF m IS NIL THEN NIL
            ELIF p(hd(m)) THEN hd(m) CONS fn(tl(m))
            ELSE fn(tl(m))
            FI;
        fn(l)
    END;
    PROC sieve = (LIST l) LIST:
        IF l IS NIL THEN NIL
        ELSE hd(l) CONS sieve(filter(
                (INT n) BOOL: n MOD hd(l) NE 0, tl(l)))
        FI;
    PROC primes = (INT n) LIST: sieve(tl(one to(n)));
    show(primes(100))
END
```

将上述代码保存入文本文件`primes.a68`中，然后使用ALGOL 68 Genie解释器执行它：

```console
$ 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
```

下面是采用了ALGOL 68RS的程序结构的Hello World样例代码，严格的说只有在`'''BEGIN'''`与`'''END'''`之间的诸行是ALGOL 68程序，第一行、第二行和最后一行都特定于`a68toc`编译器。

```bash
PROGRAM helloworld CONTEXT VOID
USE standard
BEGIN
    print(("hello, world!", newline))
END
FINISH
```

第一行给出这个程序的标识为`helloworld`而且这个名字的文件包含了这个程序；`CONTEXT VOID`短语指定这个程序独立而非嵌入到其他部分之中。第二行的`USE`加载了标准预置（prelude），`print()`就在其中。将上述代码保存入文本文件`helloworld.a68`中，然后使用ALGOL 68RS编译器`a68toc`编译并接着执行它：

```console
$ ca -u ASDFGHJ helloworld.a68
$ ./helloworld
hello, world!
```

下面是采用GCC的ALGOL 68前端`ga68`程序结构的Hello World样例代码：

```bash
hello:
begin
    puts ("Hello, world!'n")
end
```

这里的`puts()`包含在POSIX标准预置之中。将上述代码保存入文本文件`helloworld.a68`中，然后使用`ga68`编译器来编译并接着执行它：

```console
$ ga68 -o helloworld helloworld.a68
$ ./helloworld
Hello, world!
```

## 显著的语言元素

### 保留字及其等价符号

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

`'''MODE'''`，`'''OP'''`，`'''PRIO'''`，`'''PROC'''`，`'''FLEX'''`，`'''HEAP'''`，`'''LOC'''`，`'''LONG'''`，`'''REF'''`，`'''SHORT'''`，`'''STRUCT'''`，`'''UNION'''`，`'''VOID'''`。

`'''BITS'''`，`'''BOOL'''`，`'''BYTES'''`，`'''CHAR'''`，`'''COMPL'''`，`'''INT'''`，`'''REAL'''`，`'''SEMA'''`，`'''STRING'''`，`'''CHANNEL'''`，`'''FILE'''`，`'''FORMAT'''`。

`'''AT'''` `@`，`'''IS'''` `:=:`， `'''ISNT'''` `:/=:`，`'''OF'''`，`'''TRUE'''`，`'''FALSE'''`，`'''EMPTY'''`，`'''NIL'''` `○`，`'''SKIP'''` `~`。

`'''COMMENT'''` `'''CO'''` `#` `¢`，`'''PRAGMAT'''` `'''PR'''`，`'''BEGIN''' ~ '''END'''` `( ~ )`。

`'''IF''' ~ '''THEN''' ~ '''ELIF''' ~ '''THEN''' ~ '''ELSE''' ~ '''FI'''` `( ~ | ~ |: ~ | ~ | ~ )`。

`'''CASE''' ~ '''IN''' ~ '''OUSE''' ~ '''IN''' ~ '''OUT''' ~ '''ESAC'''` `( ~ | ~ |: ~ | ~ | ~ )`。

`'''FOR''' ~ '''FROM''' ~ '''TO''' ~ '''BY''' ~ '''WHILE''' ~ '''DO''' ~ '''OD'''`，`'''PAR'''`，`'''GO TO'''` `'''GOTO'''`，`'''EXIT'''`。

`'''GO TO'''`被当作两个保留字。在未修订报告的语言中，`'''OF'''`有等价符号 `→`，`'''EXIT'''`有等价符号`□`，还有保留字`'''EITHER'''`和`'''IS NOT'''`结合。

### 字符表示

<image>

“值当字符”（worthy character）是1977年出版的ALGOL 68标准硬件表示报告出于可移植性而推荐的字符集中的字符:

- 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 `&nbsp;` " # $ % '

这反映了当年一些硬件不支持在ANSI的ASCII或IBM的EBCDIC之外其他字符的事实。

传输表示采用“值当字符”时，“加上$i$乘以”符号`⊥`替代为`'''I'''`，“乘以$10$的幂”符号`⏨`和`\`替代为`'''E'''`。

<image>

ALGOL的“特殊”字符：

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

多数都可以在1965年出现的配备APL打字球与键帽后的IBM 2741终端的键盘上找到。这些字符也是Unicode标准的一部分，并且在一些流行的字体中可获得到。

### 单元

基本语言构造是“单元”（unit）。单元可以是“公式”、“封闭子句”、“例程正文”这样的构造，也可以是某个技术上需要的构造诸如赋值、跳转、越过和空无。

技术术语“封闭子句”（enclosed clause）统一了某些固有的加括号的构造，它们在其他当代语言中被称为“块”、“do语句”、“switch语句”等等。在使用关键字的时候，通常使用介入关键字的反转字符序列来终结这个包围，比如：`'''IF''' ~ '''THEN''' ~ '''ELSE''' ~ '''FI'''`、`'''CASE''' ~ '''IN''' ~ '''OUT''' ~ '''ESAC'''`和`'''FOR''' ~ '''WHILE''' ~ '''DO''' ~ '''OD'''`。这种守卫命令语法被Stephen Bourne重新使用在常用的Unix Bourne shell之中。

一个表达式还可以产生多元值（multiple value）即有多个元素的一个值，它是通过“并立子句”（collateral clause）从其他一些值构造出来的。这种构造看起来就像过程调用的参数包（pack）。

### 模态

数据类型在ALGOL 68用语中叫做“模态”（mode），其原始模态的声明符为：`'''INT'''`、`'''REAL'''`、`'''COMPL'''`（复数）、`'''BOOL'''`、`'''CHAR'''`、`'''BITS'''`、`'''BYTES'''`和`'''STRING'''`。ALGOL 68不再定义`long`、`short`和`double`这样的类型，而是提供了修饰符（modifier）`'''LONG'''`和`'''SHORT'''`。

- `'''BITS'''` – `'''BOOL'''`值的压缩向量（packed vector）。
- `'''BYTES'''` – `'''CHAR'''`值的固定大小的紧致多元组（即数组）。
- `'''STRING'''` – `'''CHAR'''`值的`'''FLEX''' [1 : 0]`（声明时无元素）的灵活多元组（即数组）。
- `'''LONG'''` – 声明`'''INT'''`、`'''REAL'''`或`'''COMPL'''`的大小为`'''LONG'''`。
- `'''SHORT'''` – 声明`'''INT'''`、`'''REAL'''`或`'''COMPL'''`的大小为`'''SHORT'''`。

ALGOL 68提供了预置常量（prelude constant）如`max real`和`long max real`等来将程序适配到不同实现之中。

复杂模态可以使用模态构造子`'''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提供了恒等声明来将标识符绑定到常量值之上。在声明给名字的标识符之时，这个名字可以被初始化为立即引用一个值；还可以将名字声明为等同于以前声明的名字而使得二者互为别名。例如：

```
'''INT''' n = 2;  # n是新建的常量，它被固定为2 #
'''INT''' m := 3;  # m是新建的局部变量的名字，这个变量的值被初始化为3 #
'''INT''' p = m;  # p是新建的常量，它被固定为同于m当前的值 #
'''INT''' q := m;  # q是新建的局部变量的名字，这个变量的值被初始化为同于m当前的值 #
'''REF INT''' r = m;  # r是新建的变量名字，它与m引用的是同一个变量 #
'''REAL''' avogadro = 6.02214076'''E'''23;  # 阿伏伽德罗常数 #
'''LONG REAL''' long pi = 3.14159 26535 89793 23846 26433 832795;
'''COMPL''' imaginary unit = 0 '''I''' 1;  # 虚数单位i即复数0 + 1i #
```

其他声明符号包括：`'''FLEX'''`、`'''HEAP'''`和`'''LOC'''`。

- `'''FLEX'''` – 所声明的名字是灵活的，就是说它可以引用任何数量元素的多元组（即数组）。
- `'''HEAP'''` – 为变量从全局堆中分配一些空闲空间。
- `'''LOC'''` – 为变量分配这个局部栈的一些空闲空间。

声明`'''REAL''' x`只是`'''REF''' '''REAL''' x = '''LOC''' '''REAL'''`的语法糖，`'''LOC''' '''REAL'''`是生成`'''REF''' '''REAL'''`模态的名字的单元。在`'''REF''' '''REAL''' x = '''LOC''' '''REAL''' := 0`中，赋值`'''LOC''' '''REAL''' := 0`导致整数`0`在被赋值给这个生成器产生的名字之前就被扩充（widen）为实数`0.0`，声明的名字`x`与生成器产生的名字二者所引用的是同一个变量。

原始声明符还包括：`'''FORMAT'''`、`'''FILE'''`、`'''CHANNEL'''`、`'''SEMA'''`、`'''COMPLEX'''`G和`'''PIPE'''`G。

- `'''SEMA'''` – 可以通过运算符`'''LEVEL'''`初始化的信号量。

ALGOL 68使用`'''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代码：

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

对于ALGOL 68，只有模态标示（indicant）`NEWMODE`出现在等号的左侧，最值得注意的是，构造的制造和读取，是从左至右而不顾及优先级的。还有ALGOL 68多元组（数组）的下界缺省的是`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;
```

### 注释和编译指导

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

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

一般而言，注释在ALGOL 68中不能嵌套。这个限制可以使用不同的注释分界符来绕过。

语用指定（pragmat）是在程序中的编译指导，典型的提示给编译器；在新近的语言中叫做“pragma”。例如：

```
'''PRAGMAT''' heap=32 '''PRAGMAT'''
'''PR''' heap=32 '''PR'''
```

### 表达式和复合语句

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以及其他一些语言之上。系列子句加上封闭它的一对圆括号或`'''BEGIN'''`与`'''END'''`叫做闭合子句（closed-clause）。

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

#### IF选择子句

```
'''IF''' 条件 '''THEN''' 诸语句 [ '''ELSE''' 诸语句 ] '''FI'''
<small>简短形式：</small>( 条件 | 诸语句 | 诸语句 )

'''IF''' 条件1 '''THEN''' 诸语句 '''ELIF''' 条件2 '''THEN''' 诸语句 [ '''ELSE''' 诸语句 ] '''FI'''
<small>简短形式：</small>( 条件1 | 诸语句 |: 条件2 | 诸语句 | 诸语句 )
```

这种方案不仅避免了悬摆else问题，还避免了必须对嵌入的语句序列使用`'''BEGIN'''`和`'''END'''`。

#### CASE选择子句

```
'''CASE''' 接转 '''IN''' 诸语句, 诸语句, ... [ '''OUT''' 诸语句 ] '''ESAC'''
<small>简短形式：</small>( 接转 | 诸语句, 诸语句, ... | 诸语句 )

'''CASE''' 接转1 '''IN''' 诸语句, 诸语句, ... '''OUSE''' 接转2 '''IN''' 诸语句, 诸语句, ... [ '''OUT''' 诸语句 ] '''ESAC'''
<small>简短形式：</small>( 接转1 | 诸语句, 诸语句, ... |: 接转2 | 诸语句, 诸语句, ... | 诸语句 )
```

采用粗体符号的选择子句的例子：

```
'''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''':
    (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);
```

粗体和简短符号的选择子句可以混合使用。

ALGOL 68允许接转（switch）具有的类型，要么是`'''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'''
```

后续的对标准ALGOL 68的扩展，允许`'''TO'''`语法元素被替代为`'''UPTO'''`和`'''DOWNTO'''`来达成小优化。这些编译器还结合了：

- `'''UNTIL'''`C – 用于更晚的循环终止。
- `'''FOREACH'''`S – 用于并行的运算于多元组（数组）之上。

### 结构与联合

ALGOL 68支持多字段结构`'''STRUCT'''`和标签联合`'''UNION'''`。`'''REF'''`可以前导于任何`'''MODE'''`，包括多元组分片和结构字段。

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

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

对上述`VALUE`的`'''UNION'''`使用共形子句（conformity clause）的`'''CASE'''`的例子：

```
VALUE v := "1234";  # 或者 v := '''EMPTY'''; #
'''CASE''' v '''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("undefined value")
'''ESAC'''
```

在未修订报告的语言中共形子句的功能通过在`'''CASE'''`子句中采用共形关系`'''CTAB'''`来实现。

### 多元组

在ALGOL 68中，不再采用术语数组或阵列（array），转而基于数学中的$n$元组（$n$-tuple）定义了多元值（multiple value）亦简称多元组（multiple）。多元组由一定数量的元素组成，每个元素都有相同的模态，有时称之为基础模态。多元组的模态由前导着一对方括号的针对每个元素的模态标示组成，它被读作“行主序和列主序的模态”（row of mode），它不同于函数式编程语言如ML中的对应于代数数据类型里积类型的“元组”（tuple）。

ALGOL 68多元组的属性之一是它的维度数目。可以声明任何数目维度的多元组，整数的二维多元组拥有模态`[,]'''INT'''`，它被读作“行套行的整数”（row-row-of-int），而实数的三维多元组拥有模态`[,,]'''REAL'''`。

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

这里的冒号分隔构造：`<small>第一个元素的下标</small> : <small>最后一个元素的下标</small>`，被称为裁剪器（trimmer）。

ALGOL 68的阵列分片，在概念上涵盖了向多元组的各个维度加下标与上标（subscript）从而访问其中特定元素的常规情况，但这个术语更常用的保留给至少一个维度不加下标的情况，比如从矩阵中切分出部分横行（row）或纵列（column）。例如：

```
'''REF''' VECTOR row = m[2,];  # 定义一个'''REF'''至矩阵的第二个横行 #
'''REF''' VECTOR col = m[,2];  # 定义一个'''REF'''至矩阵的第二个纵列 #
print ((m[,2:]));  # 打印矩阵的从第二个至最后一个的纵列 #
```

省略了裁剪器中第一个下标则假定其为此维度的下界，而省略了第二个下标则将假定其为对应的上界，两个下标都省略则产生下界为`1`的全部分片。

### 过程

过程（procedure）的`'''PROC'''`声明对参数和结果值二者要求类型指定，如果没有参数则省略参数列表，如果没有结果值则指定结果模态为`'''VOID'''`：

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

过程的返回值是在过程中求值的最后一个的表达式的值。当进行如下过程调用之时：

```
a := max of real(x, y)
```

得到等价于进行了如下变换后的结果：

```
a := '''REAL''' ('''REAL''' a = x, b = y; (a > b | a | b))
```

在这个过程之内对变量`a`和`b`的赋值是非法的。针对需要变更形式参数所提及的值的情况，ALGOL 68提供了传引用调用参数，用来在形式参数列表中指定引用，比如`'''REF REAL'''`。到过程的引用`'''REF PROC'''`也是允许的。下列例子定义一个过程，它将作为参数而指定的一个函数应用于一个数组的每个元素：

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

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

### 运算符与关联名字的单元

过程和运算符（operator）合称例程（routine），编程者可以定义新的运算符，并且这些自定义的和预定义的运算符二者都可以重载，并且它们的优先级可以由编码者变更。下列例子定义的运算符`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);
```

#### 初等和二等单元

初等单元（primary）涵盖封闭子句，此类属自身包括：所应用的标识符、调用、铸型、除了例程指示之外的指示和分片。

所应用的标识符（applied-identifier）意味着标识符在一个上下文之中被使用，并非处在其定义之中。

指示（denotation）是其所产生与任何行动都无关的构造，比如实数指示`3.14`或字符串指示`"abc"`，模态`'''VOID'''`只有一个值，其指示是`'''EMPTY'''`。在其他语言中，指示有时叫做“文字 (计算机编程)”（literal）或“常值”（constant）。

铸型（cast）构成自一个模态标示（indicant）和随后的通常为闭合子句的封闭子句。铸型可被用来提供强位置，在强上下文中能获得所有的强制。例如在`'''REF''' '''REAL''' (xx) := 1`中的`'''REF''' '''REAL''' (xx)`。

调用（call）引起（invoke）一个过程，调用在ALGOL 68 Genie中可以被部分参数化（partial parameterisation）：就是说增加实际参数到一个过程的语境（locale）中，当这个语境完全之时调用这个过程，否则发生柯里化。

优先级｜ALGOL68r1“值当字符”｜ALGOL68G

相当于12｜加下标`[~]`，分片`[~,~]`，裁剪`[~:~]`，`'''AT'''` `@`｜`'''DIAG'''`，`'''TRNSP'''`，`'''ROW'''`，`'''COL'''`

二等单元（secondary）包括生成器（generator）和选取（selection）。

优先级｜ALGOL68r1“值当字符”｜ALGOL68r0−r1｜ALGOL68G

相当于11｜`'''OF'''`，`'''LOC'''`，`'''HEAP'''`｜`→`｜`'''NEW'''`

有关的符号在技术上不是运算符，它们转而被当作“关联名字的单元”。

#### 三等单元

三等单元（tertiary）包括公式和`'''NIL'''`（可替代为`○`）。公式构成自运算符和运算元。

在ALGOL 68中对于名字只有一个指示，那就是含义为不引用任何值的`'''NIL'''`。`'''NIL'''`的模态依赖于上下文，例如：`'''REF''' '''INT''' k = '''NIL'''`，这里的`'''NIL'''`拥有模态`'''REF''' '''INT'''`。尽管`'''NIL'''`是一个名字却不可以对它赋值。

##### 一元运算符

优先级｜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'''`

##### 二元运算符及其关联的优先级

优先级｜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'''`

`'''LWB'''`（可替代为`⌊`）和`'''UPB'''`（可替代为`⌈`），这两个运算符所运算的多元组运算元的模态是`ROW`，它是指称任何行主序和列主序的模态。在未修订报告的语言中，`'''LWS'''`（可替代为`⎩`）和`'''UPS'''`（可替代为`⎧`），分别是在一个多元组（数组）的这个维度的“下界状态”和“上界状态”为固定的（fixed）的情况下返回`'''TRUE'''`。

#### 四等单元

四等单元（quaternary）包括：赋值、同一关系、例程指示（也称作例程正文）和`'''SKIP'''`（可替代为`~`）。四等单元并非语言报告中的术语，它是给从单元这个类属中除去封闭子句、初等单元、二等单元和三等单元所余下的只称为“单元”的类属的别名。

`'''SKIP'''`产生任何模态的未定义的值，并且只能出现在强上下文中。

优先级｜ALGOL68r1“值当字符”｜ALGOL68r1替代符号｜ALGOL68C,R｜ALGOL68r0−r1

相当于0｜`:=`，`'''IS'''` `:=:`，`'''ISNT'''` `:/=:`｜`:≠:` `:¬=:` `:~=:`｜`:=:=`C，`=:=`R｜`..=` `.=`，`'''IS NOT'''`，`'''CT'''` `::`，`'''CTAB'''` `::=`

在ALGOL 68中除了恒等声明之外的所有构造都有一个值，它允许链式赋值，例如`a := b := c`，这些赋值是从右至左执行的。

同一关系包括：`'''IS'''`（可替代为`:=:`）测试两个引用是否相等；`'''ISNT'''`（可替代为`:/=:`）测试两个引用是否不相等。同一关系的一侧是可以在强制时解引用来匹配另一侧的强侧，而另一侧则为软侧，不允许两侧都解引用。

### 强制

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

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

允许特定强制的境况（circumstance）叫做上下文（context）。下面列出每种上下文所固有的强度及其允许的强制：

- 软（soft）– 解过程化。
- 弱（weak) – 软强制，随后弱解引用而产生一个名字。
- 柔（meek）– 软强制，随后解引用。
- 硬（firm）– 柔强制，随后联合化。
- 强（strong）– 硬强制，随后扩充、入行或弃置。

在任何上下文中，都有拥有或产生某种模态的值的一个单元，并且在这个上下文中亦有所需的一个模态。如果两个模态不同而现有模态的值能够强制成所需模态的值，则这种强制是合法的。

平衡是将`'''IF'''`、`'''CASE'''`和共形子句中的交替者（alternative）即可供选择者，和同一关系的两侧，都强制成共同（common）的模态的手段，这使得所涉及构造的上下文会被提升（promote）从而获得这种强制。

#### 强制层级及例子

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

上下文｜上下文位置｜可获得的强制｜在此上下文中强制例子

软｜弱｜柔｜硬｜强

强｜、恒等（identity）声明的右手侧，如`~`之于`'''REAL''' …… = ~`、初始化的名字声明的右手侧，如`~`之于`'''REAL''' …… := ~`、赋值的右手侧，如`~`之于`…… := ~`、调用的实际参数，如`~`之于`……(~)`、铸型（cast）的封闭子句，如`~`之于`'''REAL'''(~)`、例程指示的单元、产生`'''VOID'''`的单元、平衡（balanced）子句的除第一部分之外的所有部分、同一关系的一侧，它可能需要解引用来适配于另一侧，如`xx`之于`xx := x; xx '''IS''' x`｜解过程化｜只在弱上下文时软强制再弱解引用｜软强制再解引用｜柔强制再联合化｜硬强制再扩充或入行或弃置｜扩充出现在没有精度损失的情况下。例如：、LONG INT$\,\Longleftarrow\,$INT、REAL$\,\Longleftarrow\,$INT、LONG REAL$\,\Longleftarrow\,$REAL、COMPL$\,\Longleftarrow\,$REAL、BOOL$\,\Longleftarrow\,$BITS、STRING$\,\Longleftarrow\,$BYTES 变量可以入行为长度为1的多元组。例如:、1INT$\,\Longleftarrow\,$INT、1REAL$\,\Longleftarrow\,$REAL

硬｜、公式的运算元，如`~`之于`~ + ~`、传输调用的实际参数｜例子： UNION(INT, REAL) var := 1

柔｜、剪标（trimscript）：裁剪器、下标和边界，产生`'''INT'''`、质询（enquiry）子句，如`~`之于`'''IF''' ~ '''THEN''' …… '''FI'''`和 `'''FROM''' ~ '''BY''' ~ '''TO''' ~ '''WHILE''' ~ '''DO''' …… '''OD'''`、调用的初等单元（被调用者），如`~`之于`~(……)`｜例子：、BOOL$\,\Longleftarrow\,$REF REF BOOL、INT$\,\Longleftarrow\,$REF REF REF INT

弱｜、分片的初等单元（被分片者），如`~`之于`~[……]`、选取的二等单元（被选取者），如`~`之于`…… '''OF''' ~`｜例子：、REF INT$\,\Longleftarrow\,$REF REF INT、REF REAL$\,\Longleftarrow\,$REF REF REF REAL、REF STRUCT$\,\Longleftarrow\,$REF REF REF REF STRUCT

软｜、赋值的左手侧，如`~`之于`~ := ……`、同一关系的另一侧，它被其中一侧可能需要解引用来匹配，如`x`之于`xx := x; xx '''IS''' x`｜例子：标准预置中的random拥有模态PROC REAL，在调用它之时发生REAL$\,\Longleftarrow\,$PROC REAL。PROC REAL rnd := random所定义的rnd拥有模态REF PROC REAL，单独使用它即rnd;之时，进行解引用接着解过程化并弃置结果的REAL。

### 正交性

ALGOL 68文法的表达依据了一些原始概念：值、模态、上下文、强制和短语（phrase）。短语是声明和单元二者之一。共有5种上下文、7种强制、22种不同的单元，和潜在无穷数量的值和模态。在每种上下文中都有可获得的强制。

正交性所称谓的是基本概念可以被没有副作用的组合。原始概念：值、模态、上下文、强制和短语，是相互独立的，它们的组合给予了ALGOL 68少有编程语言拥有的灵活性。举个例子，如果需要模态`'''INT'''`的一个值，比如在多元组的声明的裁剪器或边界中，那么在这个上下文中任何会产生一个整数的单元都可充任。其结果是ALGOL 68程序可以用宽广多样的风格来书写。例如打印从键盘读取的两个数的总和，用常规风格可以写为：

```
'''INT''' a, b;
read((a, b));
print((a + b, newline))
```

也可以等价的写为：

```
print((('''INT''' a, b;
    read((a, b));
    a + b), newline))
```

只要所书写的是合法的ALGOL 68代码，可以采用编程者喜好的任何方式。这种独立性的另一个结果是语言的规则极少有例外。

### 传输

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

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

注意预定义的过程`newpage`和`newline`作为实际参数而传送。

`print`和`read`接受可能具有各种所需模态的实际参数，这些例程的形式参数具有成行的联合模态：

```
'''PROC''' print = ([]SIMPLOUT items) '''VOID''': …… ;
'''MODE''' SIMPLOUT = '''UNION''' (
    '''INT''', '''REAL''', '''BOOL''', '''CHAR''',
    []'''INT''', []'''REAL''', []'''BOO'''L, []'''CHAR''',
    [,]'''INT''', [,]'''REAL''', [,]'''BOOL''', [,]'''CHAR''',
    …… );
'''PROC''' read = ([]SIMPLIN items) '''VOID''': …… ;
'''MODE''' SIMPLIN = '''UNION''' (
    '''REF''' '''INT''', '''REF''' '''REAL''', '''REF''' '''BOOL''', '''REF''' '''CHAR''',
    '''REF''' []'''INT''', '''REF''' []'''REAL''', '''REF''' []'''BOOL''', '''REF''' []'''CHAR''',
    '''REF''' [,]'''INT''', '''REF''' [,]'''REAL''', '''REF''' [,]'''BOOL''', '''REF''' [,]'''CHAR''',
    …… );
```

`read`使用的模态`SIMPLIN`是来自各种名字的模态的联合。`print`使用共形子句来从参数行中每个元素提取出实际的值。

在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))
```

### 并行处理

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

```
'''PROC'''
    eat = '''VOID''': (muffins -:= 1; print(("Yum!", newline))),
    speak = '''VOID''': (words -:= 1; print(("Yak...", newline)));
'''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'''`的情况下才求值。预期下面例子中的`print`不会被执行：

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

语言修订之后，已经不再允许这种从模态`'''BOOL'''`到模态`'''PROC''' '''BOOL'''`的强制和铸型。ALGOL 68 Genie将`ANDF`和`ORF`作为扩展而实现为伪运算符。

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

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

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

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

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

## 外部链接

- 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
- Из истории создания компилятора с Алгол 68
- Algol 68 – 25 Years in the USSR
- McJones, Paul, "Algol 68 implementations and dialects", Software Preservation Group, Computer History Museum, 2011-07-05

## 基本资料

- 编程范型：多范型：指令式，过程式，结构化，并发
- 设计者：阿德里安·范·韦恩加登, Barry J. Mailloux, John E. L. Peck, Cornelis H.A. Koster等人
- 发行日期：最终报告: 1968年、修订报告: 1973年
- 类型系统：静态、强类型、安全、结构类型系统
- 软件实现：Algol68toC, ALGOL 68 Genie, ALGOL 68-R, ALGOL 68C, ALGOL 68RS, ALGOL 68S, FLACC
- dialects：ALGOL 68r0 (最终报告：1968年)、ALGOL 68r1 (修订报告：1973年)
- 受影响于：ALGOL 60, ALGOL X, ALGOL Y
- 施影响于：C、C++、Bourne shell、KornShell、Bash、Steelman语言要求、Ada、Python、Seed7、Mary (编程语言)、S3 (编程语言)