ALGOL 68

ALGOL 68（源自ALGOrithmic Language 1968的缩写），一种指令式程式语言，作为ALGOL家族的成员，是官方上的ALGOL 60后继者。它的设计目标，是提供更广泛的应用，以及更严格的语法定义。
ALGOL 68的特征包括的语法，用户声明的类型和结构与标签联合类型，变量与引用参数的引用模型，可变长数组和字符串、数组与矩阵的，用户定义的运算符和运算符重载，高阶函数与匿名函数，以及并发。
概论.
ALGOL 68由负责设计。1968年12月20日，IFIP工作组2.1通过了这个语法规范，并提交IFIP大会通过且出版。
ALGOL 68的定义使用了阿德里安·范·韦恩加登发明的一种数学形式主义的两级形式文法。使用分别称为“超规则”和“元产生式规则”的两组上下文无关文法规则，生成形成一个可能无限的产生式集合，而这些常规的产生式将识别特定的ALGOL 68程序；值得注意的是，它们能够表达在很多其他编程语言的技术标准中被标记为“语义”的那种要求，其他语言的语义必须用易致歧义的自然语言叙述来表达，并接着在编译器中实现为附加到形式语言解析器的“特设”代码。
ALGOL 68设计的主要目标和原则为：
在1970年，成为了第一个投入工作的ALGOL 68编译器。在1973年9月确定的修订版本中，省略了特定特征比如过程化、gomma和形式边界。Stephen R. Bourne是ALGOL 68修订委员会成员，他选取了它的一些想法到他的Bourne shell之中。
ALGOL 68曾受到激烈的批评，最突出的是来自其设计委员会的一些成员比如C. A. R. Hoare，还有ALGOL 60编译器作者比如Edsger Dijkstra，它获评为抛弃了ALGOL 60的简单性，成为了复杂或过于笼统的想法的载体。ALGOL 68与刻意保持简单的同时代（竞争）者如C、和Pascal形成了鲜明对比。
ALGOL 68的语言定义出版后的文本长达两百多页并充斥着非标准术语，这种复杂性使得编译器实现任务变得困难，故而它曾被称为“没有实现也没有用户”。这么说只是部份真实的，ALGOL 68曾应用于一些小众市场，特别是流行于英国的（ICL）的机器之上，还有在教学角色之上。在这些领域之外，其使用相对有限。
尽管如此，ALGOL 68对计算机科学领域的贡献是深刻、广泛而持久的，虽然这些贡献大多只是在它们于后来开发的编程语言中重现之时才被公开认可。很多语言是为了应对设计这门语言时所采用的形式化方法导致的复杂性而专门开发的，其中最著名的是Niklaus Wirth的ALGOL W及其后继者Pascal；或者是针对特定角色而重新实现的，比如有些人认为Ada可以看作ALGOL 68的后继者。
1970年代的很多语言可以追溯其设计至ALGOL 68，选取一些特征，并放弃被认为太复杂或超出给定角色范围的其他特征。其中就有C语言，它受到ALGOL 68的直接影响，特别是它的强类型和结构。多数现代语言都至少可以追溯其部份语法至要么C语言要么Pascal，因而很多语言可直接或间接的经由C语言而追溯至ALGOL 68。
样例代码.
下面是Hello World样例代码，采用了的程序结构，严格的说只有在codice_1与codice_2之间的诸行是ALGOL 68程序，第一行、第二行和最后一行都特定于codice_3编译器。
<syntaxhighlight lang="bash">
PROGRAM helloworld CONTEXT VOID
USE standard
BEGIN
END
FINISH
</syntaxhighlight>
第一行给出这个程序的标识为codice_4而且这个名字的文件包含了这个程序；codice_5短语指定这个程序独立而非嵌入到其他部份之中。第二行的codice_6加载了标准预置（prelude），codice_7就在其中。将上述代码保存入文本文件codice_8中，然后使用ALGOL 68RS编译器codice_3执行它：
<syntaxhighlight lang="console">
$ ca -u ASDFGHJ helloworld.a68
$ ./helloworld
hello, world!
</syntaxhighlight>
下面的样例代码实现了埃拉托斯特尼筛法来找到小于等于100的所有素数。ALGOL 68中codice_10类似于其他语言中的空指针，codice_11表示访问codice_12的成员codice_13。
<syntaxhighlight lang="bash">
BEGIN # ALGOL68的素数筛法，基于链表实现 #
END
</syntaxhighlight>
将上述代码保存入文本文件codice_14中，然后使用ALGOL 68 Genie解释器执行它：
<syntaxhighlight lang="console">
$ a68g primes.a68
</syntaxhighlight>
显著的语言元素.
符号和保留字.
标准语言包含六十一个保留字，典型的用粗体字打印，并且其中一些还具有“简短”符号等价者：
codice_15被当作两个保留字，未修订报告的语言还有保留字codice_16和codice_17结合。
符号表示.
“臻选字符”（worthy character）是1977年出版的ALGOL 68标准硬件表示报告出于可移植性而推荐的字符集中的字符:
这反映了当年一些硬件不支持在ANSI的ASCII或IBM的EBCDIC之外其他字符的事实。
传输表示采用“臻选字符”时，“加上formula_1乘以”符号codice_19替代为codice_20，“乘以formula_2的幂”符号codice_21和codice_22替代为codice_23。
ALGOL的“特殊”字符：
多数都可以在1965年出现的配备APL打字球与键帽后的终端的键盘上找到。这些字符也是Unicode标准的一部份，并且在一些流行的字体中可获得到。
单元.
基本语言构造是“单元”（unit）。单元可以是“公式”、“封闭子句”、“例程正文”这样的构造，也可以是某个技术上需要的构造诸如赋值、跳转、越过和空无。
技术术语“封闭子句”（enclosed clause）统一了某些固有的加括号的构造，它们在其他当代语言中被称为“块”、“do语句”、“”等等。在使用关键字的时候，通常使用介入关键字的反转字符序列来终结这个包围，比如：codice_24、codice_25和codice_26。这种守卫命令语法被Stephen Bourne重新使用在常用的Unix Bourne shell之中。
一个表达式还可以产生多元值（multiple value）即有多个元素的一个值，它是通过“并立子句”（collateral clause）从其他一些值构造出来的。这种构造看起来就像过程调用的参数包（pack）。
模态.
数据类型在ALGOL 68用语中叫做“模态”（mode），其原始模态的声明符为：codice_27、codice_28、codice_29（复数）、codice_30、codice_31、codice_32、codice_33和codice_34。ALGOL 68不再定义codice_35、codice_36和codice_37这样的类型，而是提供了修饰符（modifier）codice_38和codice_39。
ALGOL 68提供了预置常量（prelude constant）如codice_57和codice_58等来将程序适配到不同实现之中。
复杂模态可以使用模态构造子codice_59、codice_60、codice_61和codice_62来创建自更简单的模态：
在一个代码块中，诸声明不必须都先于诸语句，但所有名字都必须在使用前声明。ALGOL 68提供了恒等声明来将标识符绑定到常量值之上。在声明给名字的标识符之时，这个名字可以被初始化为立即引用一个值；还可以将名字声明为等同于以前声明的名字而使得二者互为别名。例如：
其他声明符号包括：codice_71、codice_72和codice_73。
声明codice_77只是codice_78的语法糖，codice_79是生成codice_80模态的名字的单元。在codice_81中，赋值codice_82导致整数codice_83在被赋值给这个生成器产生的名字之前就被扩充（widen）为实数codice_84，声明的名字codice_13与生成器产生的名字二者所引用的是同一个变量。
原始声明符还包括：codice_86、codice_87、codice_88、codice_89、codice_90G和codice_91G。
ALGOL 68使用codice_94声明来给模态声明名字，它类似于C/C+中的codice_95和Pascal中的codice_96：
这类似于如下C99代码： 
<syntaxhighlight lang="c">
const int max = 99;
typedef struct {
} newmode[9+1][max+1];
</syntaxhighlight>
对于ALGOL 68，只有模态标示（indicant）codice_97出现在等号的左侧，最值得注意的是，构造的制造和读取，是从左至右而不顾及优先级的。还有ALGOL 68多元组（数组）的下界缺省的是codice_98，但也可以是从codice_99到codice_100的任何整数。
模态声明允许递归模态，就是说模态可直接或间接的依据自身来进行定义。这要服从一些限制，例如下列声明是非法的：
而下列声明是有效的：
注释和编译指导.
注释可以按各种方式插入：
一般而言，注释在ALGOL 68中不能嵌套。这个限制可以使用不同的注释分界符来绕过。
语用指定（pragmat）是在程序中的编译指导，典型的提示给编译器；在新近的语言中叫做“pragma”。例如：
表达式和复合语句.
ALGOL 68成为了，赋值语句所返回的值是到目的地的引用。因此下列代码在ALGOL 68中是有效的：
这种表示法也出现在C语言和Perl以及其他一些语言之中。注意在早期语言比如ALGOL 60和FORTRAN中，在标识符中的空格是允许的，所以codice_101是一个单一的标识符，因而无需采用蛇形命名法或驼峰式大小写。
另一个例子，要表达数学中codice_102从codice_103到codice_104的总和，下列ALGOL 68整数表达式就可充任：
注意，作为整数表达式，上述的代码块可以用在“整数值可以使用的任何上下”之中。代码块在ALGOL 68称为“系列子句”（serial clause），它返回其中被求值的最后一个表达式的值；这个概念也出现在LISP以及其他一些语言之上。系列子句加上封闭它的一对圆括号或codice_1与codice_2叫做闭合子句（closed-clause）。
复合语句都终止于独特的闭括号：
IF选择子句.
这种方案不仅避免了问题，还避免了必须对嵌入的语句序列使用codice_1和codice_2。
CASE选择子句.
采用粗体符号的选择子句的例子：
采用简短符号的选择子句的例子：
粗体和简短符号的选择子句可以混合使用。
ALGOL 68允许开关（switch）具有的类型，要么是codice_27要么是（独有的）codice_61。后者允许在codice_61变量上施加强类型，参见后面的联合例子。
DO循环子句.
循环语句的极小化形式是：codice_112。
下面是这种“通用”循循的完整例子：
这个构造有一些不寻常的方面：
后续的对标准ALGOL 68的扩展，允许codice_117语法元素被替代为codice_118和codice_119来达成小优化。这些编译器还结合了：
结构与联合.
ALGOL 68支持多字段结构codice_60和标签联合codice_61。codice_59可以前导于任何codice_94，包括多元组分片和结构字段。
作为递归模态的例子，下面是传统的链表的声明：
对上述codice_126的codice_61使用共形子句（conformity clause）的codice_128的例子：
在未修订报告的语言中共形子句的功能通过在codice_128子句中采用共形关系codice_130来实现。
多元组.
在ALGOL 68中，不再采用术语数组或阵列（array），转而基于数学中的formula_3元组（formula_3-tuple）定义了多元值（multiple value）亦简称多元组（multiple）。多元组由一定数量的元素组成，每个元素都有相同的模态，有时称之为基础模态。多元组的模态由前导着一对方括号的针对每个元素的模态标示组成，它被读作“的模态”（row of mode），它不同于函数式编程语言如ML中的对应于代数数据类型里的“元组”（tuple）。
ALGOL 68多元组的属性之一是它的维度数目。可以声明任何数目维度的多元组，整数的二维多元组拥有模态codice_131，它被读作“行套行的整数”（row-row-of-int），而实数的三维多元组拥有模态codice_132。
这里的冒号分隔构造：codice_133，被称为裁剪器（trimmer）。
ALGOL 68的，在概念上涵盖了向多元组的各个维度加（subscript）从而访问其中特定元素的常规情况，但这个术语更常用的保留给至少一个维度不加下标的情况，比如从矩阵中切分出部份横行（row）或纵列（column）。例如：
省略了裁剪器中第一个下标则假定其为此维度的下界，而省略了第二个下标则将假定其为对应的上界，两个下标都省略则产生下界为codice_98的全部分片。
过程.
过程（procedure）的codice_62声明对参数和结果值二者要求类型指定，如果没有参数则省略参数列表，如果没有结果值则指定结果模态为codice_136：
过程的返回值是在过程中求值的最后一个的表达式的值。当进行如下过程调用之时：
得到等价于进行了如下变换后的结果：
在这个过程之内对变量codice_137和codice_138的赋值是非法的。针对需要变更形式参数所提及的值的情况，ALGOL 68提供了传引用调用参数，用来在形式参数列表中指定引用，比如codice_80。到过程的引用codice_140也是允许的。下列例子定义一个过程，它将作为参数而指定的一个函数应用于一个数组的每个元素：
这种代码的简单性是在ALGOL 68的前身ALGOL 60中不能达成的。
运算符与关联名字的单元.
过程和运算符（operator）合称例程（routine），编程者可以定义新的运算符，并且这些自定义的和预定义的运算符二者都可以重载，并且它们的优先级可以由编码者变更。下列例子定义的运算符codice_141具有二元和一元形式二者，一元形式在一个数组的元素之上进行扫描。
初等和二等单元.
初等单元（primary）涵盖封闭子句，此类属自身包括：所应用的标识符、调用、铸型、除了例程指示之外的指示和分片。
所应用的标识符（applied-identifier）意味着标识符在一个上下文之中被使用，并非处在其定义之中。
指示（denotation）是其所产生与任何行动都无关的构造，比如实数指示codice_142或字符串指示codice_143，模态codice_136只有一个值，其指示是codice_145。在其他语言中，指示有时叫做“”（literal）或“常值”（constant）。
铸型（cast）构成自一个模态标示（indicant）和随后的通常为闭合子句的封闭子句。铸型可被用来提供强位置，在强上下文中能获得所有的强制。例如在codice_146中的codice_147。
调用（call）引起（invoke）一个过程，调用在ALGOL 68 Genie中可以被（partial parameterisation）：就是说增加实际参数到一个过程的语境（locale）中，当这个语境完全之时调用这个过程，否则发生柯里化。
二等单元（secondary）包括生成器（generator）和选取（selection）。
有关的符号在技术上不是运算符，它们转而被当作“关联名字的单元”。
三等单元.
三等单元（tertiary）包括公式和codice_10（可替代为codice_149）。公式构成自运算符和运算元。
在ALGOL 68中对于名字只有一个指示，那就是含义为不引用任何值的codice_10。codice_10的模态依赖于上下文，例如：codice_152，这里的codice_10拥有模态codice_154。尽管codice_10是一个名字却不可以对它赋值。
二元运算符及其关联的优先级.
特殊细节：
四等单元.
四等单元（quaternary）包括：赋值、同一关系、例程指示（也称作例程正文）和codice_162（可替代为codice_163）。四等单元并非语言报告中的术语，它是给从单元这个类属中除去封闭子句、初等单元、二等单元和三等单元所余下的只称为“单元”的类属的别名。
codice_162产生任何模态的未定义的值，并且只能出现在强上下文中。
在ALGOL 68中除了恒等声明之外的所有构造都有一个值，它允许链式赋值，例如codice_165，这些赋值是从右至左执行的。
同一关系包括：codice_166（可替代为codice_167）测试两个引用是否相等；codice_168（可替代为codice_169）测试两个引用是否不相等。同一关系的一侧是可以在强制时解引用来匹配另一侧的强侧，而另一侧则为软侧，不允许两侧都解引用。
强制.
强制（coercion）依据三个要件，从被强制者（coercend）产生已强制者（coercee）：在应用任何强制之前作为要被强制者的一个先验模态，在这些强制之后作为已被强制者的一个后验模态，已强制者的的语法位置（position）或类属（sort）。强制是可以级联的（cascaded）。
有7种可能的强制，其术语为解过程化（deproceduring），解引用（dereferencing）和弱解引用（weakly-dereferencing），联合化（uniting），扩充（widening）、入行（rowing）和弃置（voiding）。除了联合化之外，每种强制都在所关联的值之上，规制（prescribe）一个相应的动态效果。因此，可以使用强制来编程很多原始行动。
允许特定强制的境况（circumstance）叫做上下文（context）。下面列出每种上下文所固有的强度及其允许的强制：
在任何上下文中，都有拥有或产生某种模态的值的一个单元，并且在这个上下文中亦有所需的一个模态。如果两个模态不同而现有模态的值能够强制成所需模态的值，则这种强制是合法的。
平衡是将条件、codice_170和共形子句中的交替者（alternative）即可供选择者，和同一关系的两侧，都强制成共同（common）的模态的手段，这使得所涉及构造的上下文会被提升（promote）从而获得这种强制。
强制层级及例子.
ALGOL 68有着上下文层级，它确定在程序中特定点之上可获得的强制的种类。这种上下文分为五个层次：
正交性.
ALGOL 68文法的表达依据了一些原始概念：值、模态、上下文、强制和短语（phrase）。短语是声明和单元二者之一。共有5种上下文、7种强制、22种不同的单元，和潜在无穷数量的值和模态。在每种上下文中都有可获得的强制。
正交性所称谓的是基本概念可以被没有副作用的组合。原始概念：值、模态、上下文、强制和短语，是相互独立的，它们的组合给予了ALGOL 68少有编程语言拥有的灵活性。举个例子，如果需要模态codice_27的一个值，比如在多元组的声明的裁剪器或边界中，那么在这个上下文中任何会产生一个整数的单元都可充任。其结果是ALGOL 68程序可以用宽广多样的风格来书写。例如打印从键盘读取的两个数的总和，用常规风格可以写为：
也可以等价的写为：
只要所书写的是合法的ALGOL 68代码，可以采用编程者喜好的任何方式。这种独立性的另一个结果是语言的规则极少有例外。
传输.
传输（transput）是ALGOL 68用来称谓输入和输出设施的术语。它包括针对非格式化、格式化和二进制传输的预定义的过程。文件和其他传输设备以机器无关的方式来处理。下面的例子打印出一些非格式化的输出到“标准输出”设备：
注意预定义的过程codice_172和codice_173作为实际参数而传送。
codice_7和codice_175接受可能具有各种所需模态的实际参数，这些例程的形式参数具有成行的联合模态：
codice_175使用的模态codice_177是来自各种名字的模态的联合。codice_7使用共形子句来从参数行中每个元素提取出实际的值。
在ALGOL 68中“格式化传输”拥有自己的语法和模式（函数），具有嵌入在两个codice_179字符之间的codice_86。例如：
并行处理.
ALGOL 68支持并行处理编程。使用关键字codice_181，可以将“并立子句”转换成“并行子句”，这里的行动的同步使用信号量来控制。并行行动在ALOGL 68 Genie中被映射到线程上，如果它们在宿主操作系统上能获得到的话。例如：
未修订报告的语言.
原本依据1968年最终报告的语言在模态铸型的语法上有所不同，并且它拥有过程化（proceduring）这个特征，就是说，将一个项目的值强制成求值这个项目的一个过程。过程化意图进行惰性求值。最有用的应用是实现布尔运算符的短路求值：
在codice_182中，codice_138只在codice_137为codice_158的情况下才求值。预期下面例子中的codice_7不会被执行：
语言修订之后，已经不再允许这种从模态codice_30到模态codice_188的强制和铸型。ALGOL 68 Genie将codice_182和codice_190作为扩展而实现为伪运算符。
在语言修订之前，编程者可以通过使用叫做“gomma”的分号替代逗号（comma），从而决定一个过程的参数串行而非并立的求值。例如：
这里保证第一个实际参数求值在第二个实际参数之前，但是在平常情况：
这时编译器可以按它喜好的次序来求值实际参数。